服务模式实体框架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()暴露给控制器来管理事务?

谢谢你的帮助!

服务模式实体框架asp.net mvc

您的服务应该以这样一种方式提供功能,即消费者不必关心是否保存上下文。实际上,它不知道上下文。为什么不直接这样做呢:

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的所有"存储"优势。