乐观并发与实体框架和MySQL
本文关键字:MySQL 框架 实体 并发 乐观 | 更新日期: 2023-09-27 18:10:02
我目前正在使用实体框架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.
我的问题是MySQL的时间戳类型与MS SQL Server不同。除此之外,timestamp和datetime在MySQL中都不能提供亚秒级的精度(http://feedblog.org/2007/05/26/why-doesnt-mysql-support-millisecond-datetime-resolution/)。因此,这些类型在检测并发性问题时非常糟糕。
我可以使用什么其他数据类型来解决这个问题?我在想也许用个向导。但是,这种方法存在两个潜在的问题:MySQL将Guids存储为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
启用更改验证,应该就可以了。
这是经过测试的解决方案(适用于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,它提供了一个解决方案,在EF和非EF应用程序之间提供乐观锁定。