实体框架4和存储库模式

3

有人能解释一下使用这种模式的好处吗?

我的意思是,EF不就已经是一种仓储了吗?你不能只查询容器并返回那些对象吗?

我看到很多关于POCO、AutoMapper、依赖注入、服务层、IoC的讨论。我是不是把一堆东西混在一起了,还是它们都相关呢?

有人能向我解释一下吗?

此外,这一切如何与MVC.net、ViewModels和DataModels结合在一起呢?

谢谢, Sam

1个回答

21

这里有一些随机的问题,我会给出一些随机的答案:

  • 存储库(Repository)由 Martin Fowler 定义为“使用类似集合的接口来访问域对象,从而在域和数据映射层之间进行中介”
  • EF 是一个 ORM,它是数据映射层
  • 是的,你可以查询 EF 容器并返回对象,但是那样消费者就会“知道太多”关于底层持久化机制的信息,而不应该知道或关心-因此需要采用 Repository 模式
  • POCO 是一种技术,用于解放你的对象,使其不受持久化元数据的限制(默认情况下由 EF 代码生成使用)。它们还允许你的 POCO 兼作领域模型。
  • ViewModels 由 MVC 视图使用。
  • AutoMapper 用于轻松地将 ViewModels 转换为 Domain Models。
  • 服务层提供了控制器与仓库之间的中间地带-专门用于 IQueryable<T> 仓库,以将查询实现为具体序列(例如 ICollection<T>)。
  • IoC 用于解耦组件之间的依赖关系,从而实现良好/清晰的体系结构和卓越的可测试性(你可以向控制器传递一个 Mock 仓库,以在隔离的方式下对其进行单元测试)。

关于 #3 的详细解释:

没有使用 Repository 的示例控制器:

public class ProductsController
{
   public ActionResult GetProduct(int productId)
   {
       Product p;

       using (var ctx = new MySecretContextWhichIsNowExposed())
       {
          p = ctx.Products.SingleOrDefault(x => x.ProductId == productId);
       }

       return View(p);
   }
}

以上方法存在以下问题:

  1. 控制器直接与实体框架对象上下文一起工作,这意味着Web应用程序知道它,并且需要引用System.Data.Entity.
  2. 几乎不可能进行单元测试。您将对实际数据库进行测试,这将使其成为集成测试而不是单元测试。
  3. 控制器具有“如何检索单个产品”的逻辑,但这不应该是控制器的任务-这是领域/存储库逻辑。

带存储库的示例控制器(和IoC):

public class ProductsController
{
   private readonly IProductsRepository _repo;

   public ProductsController(IProductsRepository repo)
   {
      _repo = repo;
   }

   public ActionResult GetProduct(int productId)
   {
       Product p = _repo.FindById(productId);
       return View(p);
   }
}

为什么上述方法更好:

  1. 控制器并不了解EF,没有依赖于System.Data.Entity。
  2. 控制器不知道Repository的实现方式,通过接口工作。
  3. 控制器不提供如何检索产品的逻辑,只提供ID。
  4. 只需两行简单的代码。
  5. 单元测试很容易。在构造函数中传递一个MockProductRepository,然后就可以使用它(可以实现为内存列表)。

@RPM1984 - 你能详细说明第三点吗:italic_是的,你可以查询EF容器并返回对象,但是消费者会对底层持久性机制了解过多,而它不应该知道/关心-因此需要使用存储库模式?_italic - Sam
@RPM1984 - 这些技术/技巧是否相关? - Sam
1
@Sam Striano - 是的,它们都有关联。但有些不是 .NET 特定的(POCO's - Java 有 POJO's,DI/IoC 是一般的编程原则,就像 Repository/Service 层一样)。 - RPM1984
@RPM1984 - 仓储库代码存放在哪里?与 EF 相同的程序集中吗?您能举个分层方法的例子吗? - Sam
@Sam Striano - 涉及的内容太多了,无法给出示例,建议您谷歌搜索“ef4 repository poco”。但是,是的,它应该与EF在同一个程序集中 - 一个“MyCompany.Project.Data”程序集。 - RPM1984
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接