私は、データベースの永続性をコーディングするより現代的な方法にかなり慣れていません。私の直感は、コードが「洗練されていない」ように見えるため、何かが欠けている可能性があることを教えてくれますが、それを行う別の方法がわかりません。
注: おそらく Linq to SQL は「死んでいる」と見なされることを理解しています。私はおそらくこれをエンティティフレームワークに適用したり、後で休止状態にしたりできると仮定して、「概念を学ぶ」モードになっています。
バックグラウンド
あるデータベースからレコードを取得し、別のデータベースに入れています。取得された各レコードには、次の 2 つのケースがあります。
- 真新しい記録です。
- 値が更新されたのは、以前に挿入されたレコードです。
「古いコード」でこれを行う方法
行の存在をチェックし、それに応じて挿入と更新の両方のケースを処理する UpsertRecord というストアド プロシージャを作成します。これは入力するのが面倒で、より現代的なアプローチを検討し始めた理由の 1 つでもありました。
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
これまでに 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;
}
}
}
質問: 驚いたことに、すべてを 2 回入力しなければなりません。これが実際に必要な場合は、より経験豊富な人を驚かせることはないと確信しており、その点について確認していただければ幸いです。それ以外の場合は、同じ機能を取得する簡単な方法があります ( Salesforce の Upsert とも呼ばれます) 。 .