2011-03-11 70 views
7

假設我有一個跟蹤文件下載次數的表格,並且通過EF將該表格暴露給我的代碼。當文件被下載時,我想更新一個計數。起初,我寫了這樣的事情:如何安全地增加實體框架中的計數器

var fileRecord = (from r in context.Files where r.FileId == 3 select r).Single(); 
fileRecord.Count++; 
context.SaveChanges(); 

但是當我檢查由這些語句我注意到遞增不是發生在數據庫端,而是在我的記憶中產生的實際的SQL。所以,我的程序在數據庫中讀取計數器的值(比如2003),執行計算(新值是2004),然後明確地更新與2004年新的計值的行很顯然,這是不是從併發角度來看安全。

我希望查詢最終會尋找代替,如:

UPDATE Files SET Count = Count + 1 WHERE FileId=3 

任何人都可以建議如何我可以做到這一點?我不希望在讀取之前鎖定行,然後在更新之後解鎖,因爲我害怕阻止其他用戶的讀取(除非鎖定只有寫入的行而不是塊鎖定讀取)。

我也看着做一個實體SQL命令,但它似乎實體SQL不支持更新。

感謝

回答

1

你肯定歡迎您來電與EF存儲過程。用你顯示的SQL寫一個sproc,然後在映射到所述sproc的EF模型中創建一個函數導入。

0

您需要進行一些鎖定才能使其工作。但是你可以最小化鎖定的數量。

當您讀取計數並想要更新它時,必須將其鎖定,這可以通過將讀取和更新放入事務範圍內來完成。這將保護你免受比賽的影響。

當你讀出的數值只是想和你讀它,你可以用ReadUncommited的事務隔離級別做到這一點,這個讀然後將不會被讀鎖定/寫鎖定以上。