Qual è il modo migliore per scrivere codice che prima controlla se esiste una riga e aggiornamenti o inserti che di conseguenza?

StackOverflow https://stackoverflow.com/questions/4046981

  •  27-09-2019
  •  | 
  •  

Domanda

Sono piuttosto nuovo ai modi più moderni di codifica di persistenza del database, e la mia intuizione mi dice che probabilmente mi manca qualcosa perché il mio codice sembra "poco elegante", ma non vedo un altro modo per farlo.

Nota: ho capito forse LINQ to SQL è considerato "morto". Sono più in una modalità di "apprendimento dei concetti" assumendo che probabilmente posso applicare questo quadro entità o NHibernate successiva.

Sfondo

sto ottenendo record da un database e la loro messa in un altro. Per ogni record recuperato i casi sono due:

  1. Si tratta di un marchio nuovo record.
  2. Si tratta di un record precedentemente inserito che ha aggiornato i valori.

Come ho fatto nel mio "vecchio codice"

I scrivere una stored procedure chiamata UpsertRecord che controllato per l'esistenza di una riga e trattati entrambi i casi di inserimento e aggiornamento di conseguenza. Questo è stato un dolore di digitare e parte del motivo per cui ho iniziato a guardare un approccio più moderno.

USE [dtsynch]
GO

/****** Object:  StoredProcedure [dbo].[InsertStat_test1]    Script Date: 10/27/2010 15:04:29 ******/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[InsertStat_test1]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[InsertStat_test1]
GO

USE [dtsynch]
GO

/****** Object:  StoredProcedure [dbo].[InsertStat_test1]    Script Date: 10/27/2010 15:04:29 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[InsertStat_test1]
 @Uri nvarchar(255),
 @clicks decimal(18,0),
 @clickthru decimal(18, 0),
 @contextualImpressions decimal(18, 0),
 @currency nvarchar(3),
 @epc decimal(18, 2),
 @impressions decimal(18,0),
 @leads decimal(18,0),
 @numSales decimal(18,0),
 @numSubSales decimal(18,0),
 @pid decimal(18,0),
 @revenue decimal(18, 2),
 @saleAmount decimal(18, 2),
 @signups decimal(18, 2),
 @subSaleAmount decimal(18, 2),
 @theyGet decimal(18, 2),
 @weGet decimal(18, 2),
 @Campaign nvarchar(255),
 @Affiliate nvarchar(255),
 @Year decimal(18,0),
 @Month decimal(18,0),
 @Day decimal(18,0)
AS
BEGIN
 SET NOCOUNT ON;
 UPDATE dtsynch.dbo.Stat_test1
 SET clicks = @clicks
       ,clickthru = @clickthru
       ,contextualImpressions = @contextualImpressions
       ,currency = @currency
       ,epc = @epc
       ,impressions = @impressions
       ,leads = @leads
       ,numSales = @numSales
       ,numSubSales = @numSubSales
       ,pid = @pid
       ,revenue = @revenue
       ,saleAmount = @saleAmount
       ,signups = @signups
       ,subSaleAmount = @subSaleAmount
       ,theyGet = @theyGet
       ,weGet = @weGet
       ,Campaign = @Campaign
       ,Affiliate = @Affiliate
       ,[Year] = @Year
       ,[Month] = @Month
       ,[Day] = @Day
 WHERE Uri = @Uri
 IF (@@ROWCOUNT = 0)
 BEGIN
  INSERT INTO dbo.Stat_test1 (
    Uri 
   ,clicks
   ,clickthru
   ,contextualImpressions
   ,currency
   ,epc
   ,impressions
   ,leads
   ,numSales
   ,numSubSales
   ,pid
   ,revenue
   ,saleAmount
   ,signups
   ,subSaleAmount
   ,theyGet
   ,weGet
   ,Campaign
   ,Affiliate
   ,[Year]
   ,[Month]
   ,[Day]
  )
  VALUES (
    @Uri 
   ,@clicks
   ,@clickthru
   ,@contextualImpressions
   ,@currency
   ,@epc
   ,@impressions
   ,@leads
   ,@numSales
   ,@numSubSales
   ,@pid
   ,@revenue
   ,@saleAmount
   ,@signups
   ,@subSaleAmount
   ,@theyGet
   ,@weGet
   ,@Campaign
   ,@Affiliate
   ,@Year
   ,@Month
   ,@Day
  )
 END
END;

GO

Quello che ho finora utilizzando LINQ to SQL:

List<Stat> stats = service.DirectTrack.GetStatsForCampaign(campaign, dateForRetreivedStats);

//service.SalesForce.UpsertStats(stats);

Syncher db = new Syncher(
 @"Data Source=AARON\SQLEXPRESS;Initial Catalog=syncher;Integrated Security=True",
 XmlMappingSource.FromXml(File.ReadAllText(@"C:\zzz4\projects\svn\repo\1\statsyncher\trunk\src\DAgents.StatSyncher\Generated Code\SqlMetal\Syncher.map")));

foreach (var i in stats)
{
 var cur = (from c in db.DTStatResource
     where c.ApiUrl == i.ExternalId
     select c).FirstOrDefault();

 if (cur == null)
 {
  DTStatResource n = new DTStatResource
  {
   ApiUrl = i.ExternalId,
   Impressions = Convert.ToInt32(i.Impressions),
   ContextualImpressions = Convert.ToInt32(i.ContextualImpressions),
   Clicks = Convert.ToInt32(i.Clicks),
   ClickThru = Convert.ToDecimal(i.ClickThru),
   Leads = Convert.ToInt32(i.Leads),
   Signups = Convert.ToDecimal(i.Signups),
   NumSales = Convert.ToInt32(i.NumSales),
   SaleAmount = Convert.ToDecimal(i.SaleAmount),
   NumSubSales = Convert.ToInt32(i.NumSubSales),
   SubSaleAmount = Convert.ToDecimal(i.SubSaleAmount),
   TheyGet = Convert.ToDecimal(i.TheyGet),
   WeGet = Convert.ToDecimal(i.WeGet),
   EPC = Convert.ToDecimal(i.EPC),
   Revenue = Convert.ToDecimal(i.Revenue),
   Currency = i.Currency,
  };
  db.GetTable<DTStatResource>().InsertOnSubmit(n);
  try
  {
   db.SubmitChanges();
  }
  catch (Exception exxx)
  {
   Console.WriteLine(
    "FAILED-breaking..." + exxx.StackTrace + exxx.Message);
   break;
  }
 }
 else
 {
   cur.ApiUrl = i.ExternalId;
   cur.Impressions = Convert.ToInt32(i.Impressions);
   cur.ContextualImpressions = Convert.ToInt32(i.ContextualImpressions);
   cur.Clicks = Convert.ToInt32(i.Clicks);
   cur.ClickThru = Convert.ToDecimal(i.ClickThru);
   cur.Leads = Convert.ToInt32(i.Leads);
   cur.Signups = Convert.ToDecimal(i.Signups);
   cur.NumSales = Convert.ToInt32(i.NumSales);
   cur.SaleAmount = Convert.ToDecimal(i.SaleAmount);
   cur.NumSubSales = Convert.ToInt32(i.NumSubSales);
   cur.SubSaleAmount = Convert.ToDecimal(i.SubSaleAmount);
   cur.TheyGet = Convert.ToDecimal(i.TheyGet);
   cur.WeGet = Convert.ToDecimal(i.WeGet);
   cur.EPC = Convert.ToDecimal(i.EPC);
   cur.Revenue = Convert.ToDecimal(i.Revenue);
   cur.Currency = i.Currency;
   try
   {
    db.SubmitChanges();
   }
   catch (Exception exxx)
   {
    Console.WriteLine(
     "FAILED-breaking..." + exxx.StackTrace + exxx.Message);
    break;
   }
 }
}

DOMANDA: Quello che mi sorprende è che ho digitare ancora fuori tutto due volte. Se questo è davvero necessario Sono sicuro che non vi sorprenderà quelli più esperti e sarò felice di avere solo una conferma su questo punto, in caso contrario, c'è un modo più semplice per ottenere le stesse funzionalità ( aka upsert in Salesforce ).

È stato utile?

Soluzione

bool doInsert = (cur == null);

if (doInsert) cur = new DTStatResource();

// Do your member assignments here

if (doInsert)
{
    db.GetTable<DTStatResource>().InsertOnSubmit(n);
}

try
{
    db.SubmitChanges();
}
catch (Exception ex)
{
    // Handle exceptions
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top