2

我正在使用Entity Framework 4和SQL Server 2008 R2。我有一種情況,我想插入一個記錄,其主鍵字段可能與現有記錄匹配。我不想提出和錯誤,而是希望用新數據默默更新現有記錄。避免在EF中插入密鑰違規

我目前的實現是這樣的:

// Calculate primary key fields. 
DateTime endDate = periodTime.AddMinutes(periodMins); 
int meterId = pipe.MeterId; 

// Try to load a matching record. 
ProfileDatum lpRec = context.ProfileData.FirstOrDefault(rec => rec.MeterId == meterId && rec.EndDate == endDate); 
// If it could not be loaded, create a new one. 
if (lpRec == null) 
{ 
    lpRec = new ProfileDatum() {MeterId = meterId, 
           EndDate = endDate}; 

    // Save the object in the context. 
    context.ProfileData.AddObject(lpRec); 
} 

// Fill lpRec. 

這工作,但它的效率,可讀性和優雅很可怕。

堅持與實體框架和SQL Server 2008 R2,是否有任何方式來做類似於MySQL的「重複鍵更新」,我繼續進行,就像每次創建一個新記錄,並有數據庫更新時,有一個主要重點違規?或者也許還有其他一些優雅的方法?

效率很好,但在這種情況下次要;我追求的很簡單。這將是偉大的,是能夠 如下編寫,並忽略客戶端檢查:

// Assign primary key fields. 
var lpRec = new ProfileDatum() 
{ 
    MeterId = pipe.MeterId, 
    EndDate = periodTime.AddMinutes(periodMins) 
}; 

// Fill lpRec. 

// Save the object in the context. 
context.ProfileData.AddObject(lpRec); 

在此先感謝您的幫助,即使是說,我現有的實現是最好的方式。

回答

2

你可以使用ObjectContext.GetObjectByKey/TryGetObjectByKey嗎?

根據MSDN幫助:http://msdn.microsoft.com/en-us/library/bb738728.aspx

TryGetObjectByKey會先看看加載對象的列表,如果對象是不存在的,它會嘗試通過PK從商店加載它。如果裝載失敗(這不是在分貝),然後TryGetObjectByKey將返回false(GetObjectByKey會拋出)

 

IEnumerable<KeyValuePair<string, object>> entityKeyValues = 
    new KeyValuePair<string, object>[] 
    { 
    new KeyValuePair<string, object> ("MeterId", meterId); 
    } 

    EntityKey key = new EntityKey("YourContainerName.YourEntitySetName", entityKeyValues); 
    object entity = null; 
    if(context.TryGetObjectByKey(key, out entity)) 
    { 
    //the entity exists either in memory, or in the db 
    } 
    else 
    { 
    // you need to insert a new one 
    } 
 
1

在效率方面,讓它在DB發生將是你最好的選擇。因此,您希望將您的密鑰的StoreGeneratedPattern屬性設置爲無,然後將插入和更新方法指向使用SQL Server的MERGE功能的數據庫中的存儲過程,如下所述:http://msdn.microsoft.com/en-us/library/bb522522.aspx

這就是爲了儘可能有效地完成你所要求的。

這就是說......我認爲這是一個糟糕的設計。通過讓重複密鑰以無提示的方式回退,您可以打開太多的安全性和數據完整性漏洞,即imo。你的模型應該表達明確的和明確的意圖,你的消費代碼應該適當地使用這些意圖或者捕獲一個異常並且適當地處理這種情況。

+0

非常感謝!多快的迴應也是如此。 – 2011-01-24 18:20:42

+0

此操作正在存儲可能多次傳送的數據(冗餘消息傳送)。我不認爲有任何安全或誠信問題,但我同意明確表達意圖是一個非常好的想法(tm)。 我將離開代碼,因爲它聽起來像會通過要求開發存儲過程來增加整體複雜性,然後間接以不會立即明顯看到的方式調用C#代碼片段。 我不知道低級SQL操作可能被覆蓋。謝謝! – 2011-01-24 18:26:40

0

我個人發現你的代碼相當簡單易讀。我認爲它很好地描述了你想要做的事情,未來的程序員將會理解你的數據模型在他們看來是如何工作的。

如果您遇到重大效率問題,您可以將數據庫設置爲在未找到值時自動插入值。但是這往往會使你的模型「神奇地」行爲,所以如果效率是次要的,我會讓你的代碼保持原樣(或許使用JMarsh的建議來提高你不必進行數據庫往返的可能性)。