我对更现代的数据库持久性编码方法相当陌生,我的直觉告诉我,我可能遗漏了一些东西,因为我的代码看起来“不优雅”,但我看不到另一种方法。
注意:我知道 Linq to SQL 可能被认为是“死的”。我更多地处于“学习概念”模式,假设我可以将其应用于实体框架或稍后休眠。
背景
我从一个数据库中获取记录并将它们放入另一个数据库中。对于检索到的每条记录,有两种情况:
- 这是一个全新的记录。
- 它是先前插入的具有更新值的记录。
我是如何在“旧代码”中做到这一点的
我编写了一个名为 UpsertRecord 的存储过程,它检查是否存在行并相应地处理插入和更新情况。打字很痛苦,这也是我开始寻找更现代的方法的部分原因。
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;
}
}
}
问题:令我惊讶的是,我仍然必须输入两次。如果确实需要这样做,我相信这不会让那些更有经验的人感到惊讶,我很乐意在这一点上得到确认,否则,是否有更简单的方法来获得相同的功能(在 Salesforce 中也称为 Upsert) .