使用UnitOfWork模式自动保存DBContext
本文关键字:保存 DBContext UnitOfWork 模式 使用 | 更新日期: 2023-09-27 18:01:09
因此,使用MVC中的UnitOfWork模式,我不想每次修改对象时都调用UnitOfWork保存方法。通常使用UnitOfWork,你会做这样的事情:
if (ModelState.IsValid)
{
var user = new User()
{
Id = Guid.NewGuid(),
Username = model.Username,
Email = model.Email,
Password = model.HashedPassword()
};
unitOfWork.UserRepository.Insert(user);
unitOfWork.Save();
}
我想删除"unitOfWork.Save((;"行,只知道每次操作完成时它都会保存。因此,我在UnitOfWork的Dispose方法中添加了一个save子句:
protected virtual void Dispose(bool disposing)
{
if (context.ChangeTracker.HasChanges())
{
context.SaveChangesAsync();
}
if (!this.isDisposed)
{
if (disposing)
{
context.Dispose();
}
}
this.isDisposed = true;
}
当然,我的控制器调用了dispose:
protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
我相信HasChanges((方法可以按预期工作,并且调用了SaveChangesAsync((,但这不起作用。我想这可能与SaveChangesAsync创建的线程没有完成有关,因为它所依赖的对象被释放了?
但如果是这种情况,那么SaveChangesAsync一定是危险的,因为即使您在控制器操作中使用它,它也可能会将事务锁定几秒钟,并发现上下文在有机会保存之前已经被处理。
那么我做错了什么?我似乎找不到一种既定的方法来做到这一点,但我无法想象每个使用工作单元模式的人在每次修改任何对象时都必须记住手动调用Save方法。
虽然我同意使用Dispose()
来保存更改是个坏主意,但事情不起作用的原因是Dispose()
不是异步方法。因此,当异步处理仍在进行或尚未在后台启动时,直接调用context.SaveChangesAsync()
和context.Dispose()
可能会处理上下文。
您至少应该切换到SaveChanges()
。
作为另一种可能性,由于您声明希望每个操作都自动保存,因此您可以在结束请求时在如下位置进行保存:
MVC结束请求
这样做的模式(以这样或那样的方式(实际上被称为
每个请求的工作单元
你可以在网上找到更多关于它的详细信息,它适用于一些web应用程序(altough有很多变体(
为多个操作同时调用SaveChanges(((意味着只调用一次(具有许多优点,但并非每个应用程序都需要这些优点。如果你在某个地方有一个基本的存储库类,为什么不用Add/Remove/Update操作来定义它呢?
类似于:
public abstract RepositoryBase<T>
{
public void Add(T entity)
{
context.Add(entity);
context.SaveChanges();
}
public void Remove(T entity)
{
context.Remove(entity);
context.SaveChanges();
}
etc...
}
使用Dispose保存更改我发现非常糟糕IMO.
本次变更后工作单位的作用说明:它唯一的角色是作为上下文的包装器,确保所有存储库共享相同的上下文,但它最初的主要职责将消失。