[英]Optimistic concurrency with Entity Framework and MySQL
我目前正在使用Entity Framework 4.1和MySQL開發應用程序。 我想使用開放式並發,因此需要創建一個表結構,以允許EF檢測並發問題。 我的目標與此類似: http : //blogs.msdn.com/b/alexj/archive/2009/05/20/tip-19-how-to-use-optimistic-concurrency-in-the-entity- framework.aspx 。
我的問題是,與MS SQL Server相比,MySQL中的時間戳類型不同。 除此之外,時間戳和日期時間都無法在MySQL中提供亞秒級精度(http://feedblog.org/2007/05/26/why-doesnt-mysql-support-millisecond-datetime-resolution/)。 因此,這些類型在檢測並發問題方面將非常不利。
我還可以使用其他什么數據類型來解決這個問題? 我當時在考慮使用Guid。 但是,這種方法存在兩個潛在的問題:1. MySQL將Guid存儲為char(36),使其效率非常低下。 2.我不確定EF是否要求嚴格增加行版本,或者是否足以保證行唯一。
大警告:未測試 -大聲思考。
EF支持覆蓋SaveChanges
,因此也許一種選擇是定義一個接口,例如:
interface IVersionedRow {
int RowVersion {get;set;}
}
並將int RowVersion
屬性/字段添加到模型類和數據庫表中,並使用partial class
實現此接口(使用隱式接口實現):
partial class Customer : IVersionedRow {}
partial class Order : IVersionedRow {}
...
然后覆蓋SaveChanges
,類似於:
public override int SaveChanges(SaveOptions options)
{
foreach (ObjectStateEntry entry in
ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
{
var v = entry.Entity as IVersionedRow;
if(v != null) v.RowVersion++;
}
return base.SaveChanges(options);
}
然后應該可以用作手動實現的行版本計數器(理論上未經測試)。 保留為RowVersion
啟用更改驗證,這應該RowVersion
。
這是經過測試的解決方案(適用於EF6及更高版本)。
這是您必須在模型中執行的操作:
[Table("some_table")]
public class SomeEntity : IVersionedRow //define an interface as described previously and replace int type to long
{
...
[Column("row_version")]
public long RowVersion { get; set; }
}
然后在您的上下文中:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<SomeEntity>()
.Property(p => p.RowVersion).IsConcurrencyToken();
base.OnModelCreating(modelBuilder);
}
public override int SaveChanges()
{
var objectContextAdapter = this as IObjectContextAdapter;
if (objectContextAdapter != null) {
objectContextAdapter.ObjectContext.DetectChanges();
foreach (ObjectStateEntry entry in objectContextAdapter.ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified)) {
var v = entry.Entity as IVersionedRow;
if (v != null)
v.RowVersion++;
}
}
return base.SaveChanges();
}
現在,當您執行更新或刪除操作時,不要忘記包含DbUpdateConcurrencyException 。 它對我來說很完美。
我剛剛向MySQL .NET Connector v6.9.10提交了PR,該PR提供了針對此問題的解決方案,該解決方案在EF和非EF應用程序之間提供了樂觀的鎖定。 有關詳細信息,請參見https://stackoverflow.com/a/50147396/365261 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.