自动使用 UnitOfWork 模式保存 DBContext
Saving DBContext with UnitOfWork pattern automatically
所以在 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 方法中添加了一个保存子句:
protected virtual void Dispose(bool disposing)
{
if (context.ChangeTracker.HasChanges())
{
context.SaveChangesAsync();
}
if (!this.isDisposed)
{
if (disposing)
{
context.Dispose();
}
}
this.isDisposed = true;
}
当然我的控制器会调用处置:
protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
我确信 HasChanges() 方法按预期工作并且调用了 SaveChangesAsync(),但这不起作用。我在想这可能与 SaveChangesAsync 创建的线程没有完成有关,因为它依赖的对象已被处置?
但如果是这种情况,那么 SaveChangesAsync 一定很危险,因为即使您在控制器操作中使用它,它也可能会锁定事务几秒钟,并在它有机会保存之前发现上下文已被释放.
那我做错了什么?我似乎找不到这样做的既定方法,但我无法想象每个使用工作单元模式的人都必须记住在每次修改任何对象时手动调用 Save 方法。
同时为多个操作调用 SaveChanges()(意味着只调用一次)具有 许多 优点,但 并非每个应用程序 都需要那些优势。如果你在某处有一个基本存储库 class,为什么不使用添加/删除/更新操作来定义它,其中每个操作最后都会调用 SaveChanges()?
类似于:
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。
关于此更改后工作单元的作用的说明:
它唯一的作用是作为上下文的包装器,确保所有存储库共享相同的上下文,但它最初的主要职责将消失。
虽然我同意使用 Dispose()
来保存更改是一个坏主意,但事情不起作用的原因是因为 Dispose()
不是异步方法.因此,直接调用 context.SaveChangesAsync()
后跟 context.Dispose()
可能会在异步处理仍在进行时 处理上下文 或尚未在后台启动。
你至少应该切换到 SaveChanges()
。
作为另一种可能性,由于您声明希望每个操作都自动保存,因此您可以在结束请求时像此处这样在某处进行保存:
MVC End Request
执行此操作(以某种方式)的模式实际上称为
Unit of Work per request
你可以在网上找到更多关于它的详细信息,它适用于一些网络应用程序(虽然有很多变体)
所以在 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 方法中添加了一个保存子句:
protected virtual void Dispose(bool disposing)
{
if (context.ChangeTracker.HasChanges())
{
context.SaveChangesAsync();
}
if (!this.isDisposed)
{
if (disposing)
{
context.Dispose();
}
}
this.isDisposed = true;
}
当然我的控制器会调用处置:
protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
我确信 HasChanges() 方法按预期工作并且调用了 SaveChangesAsync(),但这不起作用。我在想这可能与 SaveChangesAsync 创建的线程没有完成有关,因为它依赖的对象已被处置?
但如果是这种情况,那么 SaveChangesAsync 一定很危险,因为即使您在控制器操作中使用它,它也可能会锁定事务几秒钟,并在它有机会保存之前发现上下文已被释放.
那我做错了什么?我似乎找不到这样做的既定方法,但我无法想象每个使用工作单元模式的人都必须记住在每次修改任何对象时手动调用 Save 方法。
同时为多个操作调用 SaveChanges()(意味着只调用一次)具有 许多 优点,但 并非每个应用程序 都需要那些优势。如果你在某处有一个基本存储库 class,为什么不使用添加/删除/更新操作来定义它,其中每个操作最后都会调用 SaveChanges()?
类似于:
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。
关于此更改后工作单元的作用的说明: 它唯一的作用是作为上下文的包装器,确保所有存储库共享相同的上下文,但它最初的主要职责将消失。
虽然我同意使用 Dispose()
来保存更改是一个坏主意,但事情不起作用的原因是因为 Dispose()
不是异步方法.因此,直接调用 context.SaveChangesAsync()
后跟 context.Dispose()
可能会在异步处理仍在进行时 处理上下文 或尚未在后台启动。
你至少应该切换到 SaveChanges()
。
作为另一种可能性,由于您声明希望每个操作都自动保存,因此您可以在结束请求时像此处这样在某处进行保存:
MVC End Request
执行此操作(以某种方式)的模式实际上称为
Unit of Work per request
你可以在网上找到更多关于它的详细信息,它适用于一些网络应用程序(虽然有很多变体)