gpt4 book ai didi

c# - 工作单元设计模式中的事务

转载 作者:太空狗 更新时间:2023-10-30 00:18:33 26 4
gpt4 key购买 nike

我无法理解工作单元的事务概念。我使用如下代码:工作类单元:

public class UnitOfWork : IDisposable
{
private readonly DbContext _context;
private bool disposed = false;

public UnitOfWork()
{
_context = new ResultsContext();
}

public IRepository<T> GetRepository<T>() where T : class
{
return new Repository<T>(_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() 的单个调用。这本身保证了所有工作都在一个简单的事务中完成。参见,例如:

In all versions of Entity Framework, whenever you execute SaveChanges() to insert, update or delete on the database the framework will wrap that operation in a transaction. This transaction lasts only long enough to execute the operation and then completes. When you execute another such operation a new transaction is started.

如果涉及多个 .SaveChanges() 或什至多个不同的 DbContext 实例,您只需要使用 TransactionScope(注意在后一种情况它甚至可以触发分布式事务,这取决于正在启动的 MSDTC 服务)。

乐观并发

我添加这条注释是因为评论:为了避免锁定数据库,EF 使用一种称为乐观并发 的机制,它基本上是在保存更改时检查自读取以来没有任何更改。有关详细信息,请参阅这两个链接:

自 EF6 以来,有多种方法可以使用所需的隔离级别启动您自己的“经典”事务。但这通常涉及锁定数据库的一部分,这会对应用程序性能产生有害影响。在大多数情况下,使用乐观并发要好得多。您会发现并发异常抛出的情况非常少,并且如链接中所述,它们可以得到处理。或者您可以将存储过程用于特定任务,例如减少在拥挤的电子商务网站上购买的产品的 UnitsInStock。也就是说,不是读取单位数量、减少它并保存更改,而是使用修改 protected 事务中的库存的存储过程或涉及隐式事务的 UPDATE 查询。

关于c# - 工作单元设计模式中的事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34609038/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com