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 DataAccess 13 { 14 public class s : IDisposable 15 { 16 protected IUnitOfWork UnitOfWork { get; set; } 17 private bool disposed = false; 18 19 protected StoreEntities Context 20 { 21 get { return (EfStoreDataContext)this.UnitOfWork; } 22 } 23 24 /// <summary> 25 /// .ctor 26 /// </summary> 27 /// <param name="unitOfWork"></param> 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 try 37 { 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 DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class 52 { 53 return this.Context.Set<TEntity>(); 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 Context 20 { 21 get { return (EfStoreDataContext)this.UnitOfWork; }
22 }
EfStoreDataContext.cs
1 public class EfStoreDataContext : StoreEntities, IUnitOfWork 2 { 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 DbSet<Contact> Contacts { get; set; } 21 public DbSet<Order> 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 IUnitOfWork 10 { 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.Repositories 10 { 11 public class OrderRepository : BaseRepository, IOrderRepository 12 { 13 14 public OrderRepository(IUnitOfWork unitOfWork) 15 : base(unitOfWork) 16 { 17 18 } 19 20 public IEnumerable<Order> GetAllOrders() 21 { 22 return this.GetDbSet<Order>(); 23 } 24 25 public Order GetByOrderId(int orderId) 26 { 27 return this.GetDbSet<Order>().Find(orderId); 28 } 29 30 public void Create(Order order) 31 { 32 this.GetDbSet<Order>().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<Order>().Find(orderId); 43 this.GetDbSet<Order>().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