我无法理解工作单元的交易概念.我使用的代码如下:工作单元类:
public class UnitOfWork : IDisposable { private readonly DbContext _context; private bool disposed = false; public UnitOfWork() { _context = new ResultsContext(); } public IRepositoryGetRepository () where T : class { return new Repository (_context); } public virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { _context.Dispose(); } } disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public Study GetStudyWithAll(string studyUid) { ResultsContext context = _context as ResultsContext; return context.Studies.Where(c => c.StudyUid == studyUid) .Include(s => s.Tasks.Select(t => t.Plugins)) .Include(s => s.Findings) .Include(s => s.Patient).FirstOrDefault(); } public void SaveChanges() { if (_context != null) { bool saved = false; do { try { _context.SaveChanges(); saved = true; } catch (DbUpdateException ex) { // Get the current entity values and the values in the database var entry = ex.Entries.Single(); //var currentValues = entry.CurrentValues; switch (entry.State) { case System.Data.EntityState.Added: // added on client, non in store - store wins entry.State = System.Data.EntityState.Modified; break; case System.Data.EntityState.Deleted: //deleted on client, modified in store entry.Reload(); entry.State = System.Data.EntityState.Deleted; break; case System.Data.EntityState.Modified: DbPropertyValues currentValues = entry.CurrentValues.Clone(); //Modified on client, Modified in store entry.Reload(); entry.CurrentValues.SetValues(currentValues); break; default: //For good luck entry.Reload(); break; } } catch (System.Data.Entity.Validation.DbEntityValidationException dbEx) { Exception raise = dbEx; foreach (var validationErrors in dbEx.EntityValidationErrors) { foreach (var validationError in validationErrors.ValidationErrors) { string message = string.Format("{0}:{1}", validationErrors.Entry.Entity.ToString(), validationError.ErrorMessage); // raise a new exception nesting // the current instance as InnerException raise = new InvalidOperationException(message, raise); } } throw raise; } } while (!saved); } } public DbContext Context { get { return _context; } } }
我使用它的方式:
using (var uow = new UnitOfWork()) { //////some stuff/// uow.SaveChanges(); }
问题是:工作单元的上下文是等于事务,还是我需要添加:
using (TransactionScope transaction = new TransactionScope())
周围.
我知道saveChanges是用事务包装的,我不知道的是:整个上下文是否包含在事务中.我的意思是,我可以确定在上下文的生命周期中我读取的数据(不保存或更新)没有改变吗?
您的工作单元实施使用DbContext
单个调用.SaveChanges()
.这保证了所有工作都是在一个简单的交易中完成的.例如,见:
EF Code First DBContext和Transactions
使用交易(EF6以上):
在所有版本的Entity Framework中,每当您执行SaveChanges()以在数据库上插入,更新或删除时,框架都会将该操作包装在事务中.此事务仅持续足够长的时间来执行操作然后完成.执行另一个此类操作时,将启动一个新事务.
TransactionScope
如果涉及几个.SaveChanges()
甚至几个不同的DbContext
实例,您只需要使用a (请注意,在后一种情况下,它甚至可以触发分布式事务,这取决于MSDTC服务的启动).
我添加了这个注释因为注释:为了避免锁定数据库,EF使用了一种名为Optimistic concurrenty的机制,它基本上检查自保存更改后读取的内容没有任何更改.有关更多信息,请参阅以下两个链接
乐观并发模式
保存更改并管理并发
从EF6开始,您可以通过所需的隔离级别启动自己的"经典"事务.但这通常涉及锁定部分数据库,这可能会对应用程序性能产生有害影响.在大多数情况下,使用乐观并发更好.您会发现很少发生并发异常的情况,并且如链接中所述,可以处理它们.或者,您可以将存储过程用于特定任务,例如,减少UnitsInStock
在拥挤的电子商务站点中购买的产品.即,不是读取单位数量,减少单位数量,保存更改,而是使用存储过程修改受保护事务中的库存或UPDATE
涉及隐式事务的查询.