在做项目时,通常我们对乐观并发有几种处理模式
1. 告诉用户此数据已被其他人捷足先登,更改了。你就算新一下重来吧。
2.直接把数据覆盖上去,我最大。
3.用被人的数据.
这里给出 code first 的做法
[Table("product")]
[JsonObject(IsReference= true)]public classProduct
{
[Key]public int id { get; set; }public string code { get; set; }public DateTime dateCreated { get; set; }
[ConcurrencyCheck]//关键
public DateTime dateModified { get; set; }public virtual List categories { get; set; }public virtual List colors { get; set; }
}
MySQL 要有这个column
ALTER TABLE `db`.`product` ADD COLUMN `dateModified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
using (DB db = newDB())
{var product = db.products.Find(1);
product.code= "mk99";try{
db.SaveChanges();
}catch (DbUpdateConcurrencyException ex) //DbUpdateConcurrencyException
{var objContext =((IObjectContextAdapter)db).ObjectContext;var entry =ex.Entries.Single();//objContext.Refresh(RefreshMode.ClientWins, entry.Entity);
objContext.Refresh(RefreshMode.StoreWins, entry.Entity);
db.SaveChanges();
}
}
用DBUpdateConcurrencyException捕获异常,然后我们就可以观察这个entry的种种资料来定义我们的处理。
objContext.Refresh 是微软提供的方案, RefreshMode.StoreWins 就是用当前database的最新数据替换本地数据, ClientWins 就是覆盖本地数据到数据库中啦。
用 fluent api
modelBuilder.Entity()
.Property(e => e.rowLastModifiedDT).IsConcurrencyToken();
更新 :
rowVersion 是 byte[] , 使用 SequenceEqual 或 base64 来检查
if (!FAQSQL.rowVersion.SequenceEqual(FAQ.GetEntity().rowVersion))
{
//concurrency
}
if(Convert.ToBase64String(FAQSQL.rowVersion) == Convert.ToBase64String(FAQ.GetEntity().rowVersion))
{
//concurrency
}