2012-04-22 60 views
0

我已經基本上得到了一個循環,如下所示:如何更新實體框架中的重複鍵?

foreach(var file in files) 
{ 
    // ... 
    db.Images.Add(new ImageFingerPrint { FileName = file, FingerPrint = fingerprint }); 
} 

int recordsAffected = db.SaveChanges(); 

FileName是PK。如果它已經存在於數據庫中,我只想更新它的FingerPrint。基本上做一個REPLACE我想。

如果這不容易/可能,我怎麼簡單地截斷整個表?

回答

2

您可以

db.Images.Clear(); 
db.SaveChanges(); 

假設沒有外鍵約束截斷表。

如果你想獲得一個現有的項目,嘗試LINQ查詢:

var existing = (from im in db.Images 
       where im.FileName.Equals(file) 
       select im).SingleOrDefault(); 
if(existing != null) 
    existing.FingerPrint = fingerprint; 
else 
    db.Images.Add(...) 
db.SaveChanges(); 
+0

'DbSet '[has no method called Clear](http://msdn.microsoft.com/zh-cn/library/gg679592%28v=vs.103%29.aspx)。另外,如果不先查詢它,是不是有辦法更新它? MySQL有「重複更新」;不確定MS SQL是否有類似的東西。 – mpen 2012-04-22 19:19:22

+1

@Mark - 這不是MS SQL,這是實體框架。它旨在與許多不同的數據庫提供程序一起工作,因此通常不得不避開有用的功能,因爲它們不受所有提供程序的支持。 EF中沒有重複更新功能。 – 2012-04-22 19:31:48

2

,我用的是

foreach(var file in files) 
{ 
    var image = db.Images.SingleOrDefault(i => i.FileName == file); 
    if (item == null) 
    { 
     image = new ImageFingerPrint() { FileName = file }; 
     db.Images.Add(image); 
    } 

    image.FingerPrint = fingerprint; 
}  
db.SaveChanges(); 

這是比較容易了以往的模式,當物體具有一定的數據庫 - 生成的字段,如IDENTITY主鍵,CreatedDate列或時間戳。檢查這些字段是否爲默認值很簡單,如果它們是新的,應該「添加」。

根據你的循環的複雜性可能要確定現有的「和「新」的文件名的前期 -

var existing = files.Where(f => db.Images.Contains(f)); 
// & use .ToList() if you're going to be iterating the collection multiple times 

foreach (file in existing) 
{ 
    // updates 
} 

foreach (var file in files.Except(existing)) 
{ 
    // inserts 
} 

我使用這種方法時,有性能優勢 - 例如其中一項操作可以作爲批量操作完成,另一項操作不能。否則,如果插入和更新操作明顯不同,它可以使代碼更清晰。