服务模式实体框架asp.net mvc
本文关键字:net mvc asp 框架 模式 实体 服务 | 更新日期: 2023-09-27 18:15:53
我想在我的asp.net mvc实体框架6项目中进行单元测试,它迫使我查看我的代码。我将控制器暴露在我的环境中,并决定我应该将其分离出来。我最初考虑的是存储库/UoW模式,但在阅读了很多内容后,我决定使用DI的简单服务模式(即,将控制器注入具有GetProducts()
, FindProduct()
等的服务)。
我的问题与此模式中的变更跟踪有关。在控制器方法中完成了很多事情之后,我只调用SaveChanges()
,但将所有内容分开,使方法如下:
public void AddRequest(Request request)
{
using (PricedNotesContext ctxt = new PricedNotesContext())
{
ctxt.Requests.Add(request);
ctxt.SaveChanges();
}
}
public void DeleteRequestData(BaseRequestData reqData)
{
using (PricedNotesContext ctxt = new PricedNotesContext())
{
ctxt.RequestData.Remove(reqData);
ctxt.SaveChanges();
}
}
在上面,您看到SaveChanges()
被调用了两次。但我只想叫一次。我只希望在两个操作都成功完成的情况下保留更改。建议的解决方案只是有一个叫做SaveChanges()
和Dispose()
的方法,显然调用SaveChanges()
和Dispose()
暴露给控制器来管理事务?
谢谢你的帮助!
您的服务应该以这样一种方式提供功能,即消费者不必关心是否保存上下文。实际上,它不知道上下文。为什么不直接这样做呢:
public class EfNotesService : INotesService
{
public ExecuteSomeBusinessOperation(input parameters here)
{
// Validate input parameters
using (PricedNotesContext ctxt = new PricedNotesContext())
{
ctxt.Requests.Add(...);
ctxt.RequestData.Remove(...);
// other logic
ctxt.SaveChanges();
}
}
}
或者更好的是,您还可以使用依赖注入在请求开始时注入上下文,并在请求结束时处理它。然后这个上下文被注入到EfNotesService的构造函数中,然后你就可以不用using语句来使用它了:
public class EfNotesService : INotesService
{
private readonly PricedNotesContext _ctxt;
public EfNotesService(PricedNotesContext ctxt )
{
_ctxt = ctxt;
}
public ExecuteSomeBusinessOperation(input parameters here)
{
// Validate input parameters
_ctxt .Requests.Add(...);
_ctxt .RequestData.Remove(...);
// other logic
_ctxt .SaveChanges();
}
}
就像这样,相同的上下文可以跨越多个服务,并且您不必担心在这些服务中创建和处置上下文。
此外,在您的服务操作中,您当然可以使用业务组件甚至域层来执行业务逻辑,而不是在服务中执行所有操作。
并添加一个全局异常处理程序来优雅地处理异常。
我是这么想的
public class EfNotesService : INotesService
{
private readonly PricedNotesContext _ctxt = new PricedNotesContext();
public IEnumerable<Request> GetAllRequests()
{
return _ctxt.Requests.ToList();
}
public void SaveRequest(Request request)
{
_ctxt.Entry(request).State = EntityState.Modified;
}
public void DeleteRequestData(BaseRequestData reqData)
{
_ctxt.RequestData.Remove(reqData);
}
// ...
// Other methods...
// ...
// Transaction control
public void SaveChanges()
{
_ctxt.SaveChanges();
}
public void Dispose()
{
_ctxt.Dispose();
}
}
它不是UoW或Repository,但它很简单,而且工作得很好。此外,我还保留了DbContext的所有"存储"优势。