EntityFramwork--处理数据并发问题时支持乐观并发,即假定最佳场景(这里是指数据在更新过程中没有发生变化)
具体看《Beginning ASP.NET 4.5 Databases》P188-189:
本书源代码下载地址:
http://www.codeplex.com/Download?ProjectName=CommonServiceLocator&DownloadId=45067
以一下是截取源代码的实现Unit of work、并发、事务的BaseRepository:
BaseRepository.cs:
1 using System; 2 using System.Collections.Generic; 3 using System.Data; 4 using System.Data.Entity; 5 using System.Data.Entity.Infrastructure; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Transactions;10 using Repository;11 12 namespace DataAccess13 {14 public class s : IDisposable15 {16 protected IUnitOfWork UnitOfWork { get; set; }17 private bool disposed = false;18 19 protected StoreEntities Context20 {21 get { return (EfStoreDataContext)this.UnitOfWork; }22 }23 24 ///25 /// .ctor26 /// 27 /// 28 public BaseRepository(IUnitOfWork unitOfWork)29 {30 if (unitOfWork == null) throw new ArgumentNullException("unitOfWork");31 this.UnitOfWork = unitOfWork;32 }33 34 public void Save()35 {36 try37 {38 using(var scope = new TransactionScope(TransactionScopeOption.RequiresNew))39 {40 this.Context.SaveChanges();41 scope.Complete();42 }43 }44 catch (DbUpdateConcurrencyException concurrencyException)45 {46 concurrencyException.Entries.Single().OriginalValues.SetValues(concurrencyException.Entries.Single().GetDatabaseValues());47 throw;48 }49 }50 51 protected virtual DbSetGetDbSet () where TEntity : class52 {53 return this.Context.Set ();54 }55 56 protected virtual void SetEntityState(object entity, EntityState entityState)57 {58 this.Context.Entry(entity).State = entityState;59 }60 61 protected virtual void Dispose(bool disposing)62 {63 if (!this.disposed)64 {65 if (disposing)66 {67 this.Context.Dispose();68 }69 }70 this.disposed = true;71 }72 73 public void Dispose()74 {75 Dispose(true);76 GC.SuppressFinalize(this);77 } 78 }79 }
--------------------------- (一).事务
38 using(var scope = new TransactionScope(TransactionScopeOption.RequiresNew))39 {40 this.Context.SaveChanges();41 scope.Complete();42 }
使用事务的目的:在某个场景中,需要更新多个数据上下文实例,并想要把这些更新放在一个事务中。 2.
--------------- (二)并发
44 catch (DbUpdateConcurrencyException concurrencyException)45 {46 concurrencyException.Entries.Single().OriginalValues.SetValues(concurrencyException.Entries.Single().GetDatabaseValues());47 throw;48 }
EF框架处理并发的方式:
方式1:
让客户端决定状态----让项的原始值设置为从数据库中获取的值:
concurrencyException.Entries.Single().OriginalValues.SetValues(concurrencyException.Entries.Single().GetDatabaseValues());
方式2:
让客户端决定状态----用存储中的值刷新新实体值:
concurrencyException.Entries.Single().Reload(); 方式3: 自定义一种方案,选择合适的选项。 --------------------- (三)工作单元 Unit of work
EF中的Unit Of Work机制
(假设StoreEntities 实例的变量名为contexDb)
contexDb.Entry(Order).State = System.Data.EntityState.Modified; //
------------------------------------------------ 下面代码是设计一个实现了Unit of work机制和Repository模式的具体实现:
56 protected virtual void SetEntityState(object entity, EntityState entityState)57 {58 this.Context.Entry(entity).State = entityState;59 }
this.Context是
19 protected StoreEntities Context20 {21 get { return (EfStoreDataContext)this.UnitOfWork; } 22 }
EfStoreDataContext.cs
1 public class EfStoreDataContext : StoreEntities, IUnitOfWork2 {3 public new void SaveChanges()4 {5 base.SaveChanges();6 }7 }
EF生成的访问数据的DbContext
1 namespace DataAccess 2 { 3 using System; 4 using System.Data.Entity; 5 using System.Data.Entity.Infrastructure; 6 using Entities; 7 8 public partial class StoreEntities : DbContext 9 {10 public StoreEntities()11 : base("name=StoreEntities")12 {13 }14 15 protected override void OnModelCreating(DbModelBuilder modelBuilder)16 {17 throw new UnintentionalCodeFirstException();18 }19 20 public DbSetContacts { get; set; }21 public DbSet Orders { get; set; }22 }23 }
IUnitofWork.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Repository 8 { 9 public interface IUnitOfWork10 {11 void SaveChanges();12 }13 }
使用了工作单元 (Unit of work)机制的OrderReposiory:
OrderReposiory.cs:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using Entities; 7 using Repository; 8 9 namespace DataAccess.Repositories10 {11 public class OrderRepository : BaseRepository, IOrderRepository12 {13 14 public OrderRepository(IUnitOfWork unitOfWork)15 : base(unitOfWork)16 {17 18 }19 20 public IEnumerableGetAllOrders()21 {22 return this.GetDbSet ();23 }24 25 public Order GetByOrderId(int orderId)26 {27 return this.GetDbSet ().Find(orderId);28 }29 30 public void Create(Order order)31 {32 this.GetDbSet ().Add(order);33 }34 35 public void Update(Order order)36 {37 this.SetEntityState(order, System.Data.EntityState.Modified);38 }39 40 public void Delete(int orderId)41 {42 var order = this.GetDbSet ().Find(orderId);43 this.GetDbSet ().Remove(order);44 }45 }46 }
根据上面的设计,这行代码:
37 this.SetEntityState(order, System.Data.EntityState.Modified); 最终调用EF框架生成的
public partial class StoreEntities : DbContext 的方法
contexDb.Entry(Order).State = System.Data.EntityState.Modified; //EF中的Unit Of Work机制
假设StoreEntities 实例的变量名为contexDb