2010-07-06 61 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