2

我正在阅读存储库和 UOW 模式,似乎 UOW 需要一堆数据,对内存中的数据进行修改,然后在某个点提交更改。如果不需要,我不想实现另一层所以我试图将一些 UOW 职责委托给我的存储库(即保存)。

我当前应用程序的存储库立即执行保存,如下所示:

public void DeleteBox(int BoxId)
        {
            var Box = GetBox(BoxId);
            if (Box != null)
            {
                foreach (var subBox in Box.Boxes.ToList())
                {
                    DeleteBox(subBox.BoxId);
                }

                if (Box.ParentBox != null)
                {
                    Box.ParentBox.Boxs.Remove(Box);
                    _db.SaveChanges();
                }
                _db.Boxs.Remove(Box);
                _db.SaveChanges();
            }
            else throw new InvalidOperationException("Cannot delete Box because it doesn't exist");
        }

代码当前“有效”,但我想知道在这里执行 SaveChanges 是否不太理想。当我开始构建 WebAPI 时,是否应该考虑从控制器操作调用 saveChanges,并修改存储库中应用程序的状态?任何帮助我更好地理解应该如何进行储蓄的文章或参考资料都会很棒——我现在有点不知所措。

4

1 回答 1

2

就个人而言,我喜欢创建一个完整的存储库类来处理域模型对象的所有 CRUD 操作,并通过接口将此存储库传递给 MVC 控制器。然后,控制器根据应用程序逻辑在存储库上执行各种方法。

我觉得这种方法有两个主要优点:

  1. 您可以将存储库中的数据访问代码与控制器中的应用程序逻辑代码完全分开。因此,您的存储库对数据访问负有全部责任,而您的控制器维护应用程序逻辑。
  2. 这是为测试构建事物的有效方法。通过通过接口将存储库传递到控制器,您可以通过模拟框架(例如 RhinoMocks 或 Moq)对控制器进行完整的可测试性。您的数据访问代码很难或不可能进行有效测试,它们被集中到一个不可测试的类中。

例如,假设我想要一个控制器来对 Product 类执行完整的 CRUD 操作。我将创建一个存储库接口和实现,如下所示。请注意,存储库实现需要对象关系映射器 (ORM) 或数据访问层的实例。在此示例中,我通过构造函数中的 ISession 接口传入 nHibernate Session 对象的实例。

public interface IProductRepo
{
    List<Product> GetProducts();
    Product GetProduct(int Id);
    void DeleteProduct(int Id);
    void CreateProduct(Product product);
    void UpdateProduct(Product product);
}

public class ProductRepo : IProductRepo
{
    public ProductRepo(ISession session)
    {
         _session = session;  
    }

    public Product GetProduct(int Id)
    {
         return _session<Product>().Get(Id);
    }

    //Implementation of other methods of IProductRepo

     ISession _session;
}

然后可以通过构造函数注入(我最喜欢的)或属性注入将这个 repo 传递给控制器​​。所以你的控制器看起来像这样:

public class ProductController : ApiController
{
    public ProductController(IProductRepo repo)
    {
        _repo = repo;
    }
    public List<Product> GetProducts()
    {
        //other code as needed
        return _repo.GetProducts();
    }
    public Product GetProduct(int id)
    {
        //other code as needed
        return _repo.GetProduct(id);
    }
    public void PostProduct(Product product)
    {
        _repo.CreateProduct(product);
        //other code as needed
    }
    public void PutProduct(Product product)
    {
        _repo.UpdateProduct(product);
        //other code as needed
    }
    public void DeleteProduct(int id)
    {
        _repo.DeleteProduct(id);
        //other code as needed
    }
}

Microsoft 有一篇很好的文章,介绍了 Web API 的基本示例。

编辑:存储库模式

用马丁·福勒的话说

存储库在域和数据映射层之间进行调解,就像内存中的域对象集合一样。

它通常与对象关系映射器 (ORM) 或数据访问层(如 nHibernate 或实体框架)结合使用。因此,您的存储库将采用 ORM 或数据访问类的实例,该实例实际上执行对持久层的写入和读取。存储库用于封装您对 ORM/数据访问类的所有查询和 CRUD 操作。

于 2013-03-03T21:50:57.430 回答