簡體   English   中英

實體框架和MySQL的樂觀並發

[英]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.

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