2010-07-06 68 views
6

SQL Server 2008中耳鼻喉科 ASP.NET MVC 2.0 LINQ到SQL执行合并使用LINQ to SQL

我建立一个游戏网站,当一个特定的播放器(椿)击落了特定的怪物,跟踪(老板)。表看起来像:

int ToonId 
int BossId 
datetime LastKillTime 

我使用3D第三方服务,让我回最新信息(香椿,老板,时间)。
现在我想用新的信息更新我的数据库。
蛮力的方法是做逐行upsert。但它看起来很丑(代码方面),并且可能也很慢。

我认为更好的解决方案是插入新数据(使用临时表?),然后运行MERGE语句。

这是个好主意吗?我知道临时表是“更好避免”。我应该为此操作创建一个永久的“临时”表吗?
或者我应该只读取整个当前集(最多100行),合并并将其从应用程序内恢复?

任何指针/建议总是赞赏。

回答

6

ORM是执行批处理操作的错误工具,Linq-to-SQL也不例外。在这种情况下,我认为你已经选择了正确的解决方案:将所有条目快速存储在临时表中,然后使用合并执行UPSERT。

将数据存储到临时表的最快方法是使用SqlBulkCopy将所有数据存储到您选择的表中。

-1

看起来像一个简单的插入。

private ToonModel _db = new ToonModel(); 
Toon t = new Toon(); 
t.ToonId = 1; 
t.BossId = 2; 
t.LastKillTime = DateTime.Now(); 
_db.Toons.InsertOnSubmit(t); 
_db.SubmitChanges(); 
+2

如果我已经有ID = 1的卡通,它不会给我“重复的ID”吗? – 2010-07-06 16:40:56

6

如果您使用LINQ到SQL,upserts没有那么难看..

foreach (var line in linesFromService) { 
    var kill = db.Kills.FirstOrDefault(t=>t.ToonId==line.ToonId && t.BossId==line.BossId); 
    if (kill == null) { 
     kill = new Kills() { ToonId = line.ToonId, BossId = line.BossId }; 
     db.Kills.InsertOnSubmit(kill); 
    } 
    kill.LastKillTime = line.LastKillTime; 
} 
db.SubmitChanges(); 

不是艺术作品,但比SQL更好。而且,只有100行,我不会太在意性能。

+0

我同意,性能在这里不是一个问题,所以对丑陋的SQL使用LINQ方法 – 2010-11-17 00:58:53

0

要在不查询记录的情况下进行更新,可以执行以下操作。它仍然会打到DB一次,以检查是否存在记录,但不会拉记录:

var blob = new Blob { Id = "some id", Value = "some value" }; // Id is primary key (PK) 

if (dbContext.Blobs.Contains(blob)) // if blob exists by PK then update 
{ 
    // This will update all columns that are not set in 'original' object. For 
    // this to work, Blob has to have UpdateCheck=Never for all properties except 
    // for primary keys. This will update the record without querying it first. 
    dbContext.Blobs.Attach(blob, original: new Blob { Id = blob.Id }); 
} 
else // insert 
{ 
    dbContext.Blobs.InsertOnSubmit(blob); 
} 
dbContext.Blobs.SubmitChanges(); 

为这个扩展方法见here