簡體   English   中英

實體框架使用存儲過程的並發問題

[英]Entity Framework concurrency issue using stored procedures

我正在使用ASP.NET為零售公司構建應用程序。 我使用實體框架(模型優先)作為我的數據訪問層。 我正在使用存儲過程來執行我的CRUD操作,並且所有列都已映射,並且似乎正確,因為所有CRUD功能都按預期工作。

但我在DELETE操作中遇到並發問題。

我已經在表中添加了一個TimeStamp列,我正在進行CRUD操作。 UPDATE操作正常,因為它是通過主鍵和TimeStamp值更新。 因此,如果UPDATE操作沒有影響任何行,則由於TimeStamp值的更改,Entity Framework會拋出OptimisticConcurrencyException

DELETE操作的工作原理與刪除主鍵和TimeStamp值的原理相同。 但是,當實體和數據庫之間的TimeStamp值不匹配時,不會拋出異常。

在C#delete方法中,我首先檢索最新記錄,然后將TimeStamp屬性更新為另一個TimeStamp值(它可能與檢索到的值不同)。 在使用SQL事件探查器進行一些調查之后,我可以看到執行了DELETE存儲過程,但傳遞給存儲過程的TimeStamp參數是最新的TimeStamp值, 而不是我將TimeStamp屬性設置為的值 因此,記錄被刪除,實體框架不會拋出異常。

為什么實體框架仍然將檢索到的TimeStamp值傳遞給存儲過程而不是我分配屬性的值? 這是設計還是我錯過了什么?

任何幫助將不勝感激! (當你需要她時,Julie Lerman在哪里!:-))

EF中的樂觀並發工作正常。 即使有存儲過程。

ObjectContext.DeleteObjects將實體的原始值傳遞給刪除函數。 這是有道理的。 原始值用於標識要刪除的行。 刪除對象時,您(通常)不會對您的實體進行有意義的編輯。 您對EF的期望是什么? 寫? 要記錄什么?

將修改后的數據傳遞給刪除函數的一個合法用途是,當您想要跟蹤某些其他表中的刪除時您需要輸入一些在數據庫層無法訪問的信息,僅在業務層。 示例包括應用程序級別用戶名或要刪除的原因。 在這種情況下,您需要使用此值構造實體作為原始值 一種方法:

var x = db.MyTable.Single(k => k.Id == id_to_delete);
x.UserName = logged_in_user;
x.ReasonForChange = some_reason;
// [...]
db.ObjectStateManager.ChangeObjectState(x, EntityState.Unchanged);
db.MyTable.DeleteObject(x);
db.SaveChanges();

當然,更好的策略可能是在業務層公開進行。


我不理解你的rowversion / timestamp用例。

  1. 要避免並發問題,請將原始時間戳傳遞給修改代碼。 這樣,它可以與數據庫中的當前值進行比較,以檢測自上次讀取后記錄是否已更改。 將它與新值進行比較毫無意義。

  2. 您通常使用由數據庫自動更新的更改標記,如SQL Server中的rowversion / timestamp,Oracle中的rowversion或PostgreSQL中的xmin。 您不會在代碼中更改其值。

  3. 但是,如果您手動維護行版本,則需要提供:

    a)要插入和更新要寫入的新版本,以及

    b)舊版本(從數據庫讀取)更新和刪除以檢查並發更改。

    您不會發送新值來刪除。 你不需要。 此外,在使用存儲過程進行修改時,最好在過程中計算新版本並將其返回給應用程序,而不是相反。

很難說沒有看到任何代碼,但也許當回發發生時,頁面正在重新綁定,然后你的刪除方法被觸發? 在任何方法數據綁定表單控件(我假設它是OnLoad或OnInit),你用if ( !this.IsPostBack ) { ... }包裝任何數據綁定調用嗎?

另外我不確定你是否有理由在viewstate / session變量中顯式存儲並發標志,但是更好的方法(imo)是將時間戳添加到FormView / GridView的DataKeyNames屬性中(即: <asp:FormView ID='blah' runat='server' DataKeyNames='Id, Timestamp'>

這樣您就不必擔心手動存儲或更新時間戳。 ;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM