使用Entity Framework时是否真的有必要实现存储库?

Iva*_*ken 6 entity-framework repository

我正在研究MVC和EF,我经常在关于这些主题的文章中看到控制器通过Repository对象操作数据而不是直接使用LINQ to Entities.

我创建了一个小型Web应用程序来测试一些想法.它将以下接口声明为数据存储的抽象

public interface ITinyShopDataService
{
    IQueryable<Category> Categories { get; }
    IQueryable<Product> Products { get; }
}
Run Code Online (Sandbox Code Playgroud)

然后我有一个继承自生成的类TinyShopDataContext(继承自ObjectContext)并实现ITinyShopDataService的类.

public class TinyShopDataService : TinyShopDataContext, ITinyShopDataService
{
    public new IQueryable<Product> Products
    {
        get { return base.Products; }
    }

    public new IQueryable<Category> Categories
    {
        get { return base.Categories; }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,控制器使用ITinyShopDataService的实现来获取数据,例如用于显示特定类别的产品.

public class HomeController : Controller
{
    private ITinyShopDataService _dataService;

    public HomeController(ITinyShopDataService dataService)
    {
        _dataService = dataService;
    }

    public ViewResult ProductList(int categoryId)
    {
        var category = _dataService.Categories.First(c => c.Id == categoryId);
        var products = category.Products.ToList();
        return View(products);
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为上面的控制器具有一些积极的属性.

  • 由于注入了数据服务,因此很容易测试.
  • 它使用LINQ语句以与实现无关的方式查询抽象数据存储.

因此,我没有看到在控制器和ObjectContext派生类之间添加存储库的任何好处.我错过了什么?(对不起,第一篇帖子有点太长了)

Cra*_*ntz 5

你可以根据你的建议测试你的控制器.

但是,如何在数据服务中测试查询?想象一下,您有非常复杂的查询行为,有多个复杂的查询来返回结果(检查安全性,然后查询Web服务,然后查询EF等).

你可以将它放在控制器中,但这显然是错误的.

当然,它应该放在你的服务层.您可以模拟/伪造服务层以测试控制器,但现在您需要测试服务层.

如果你能在不连接数据库(或网络服务)的情况下做到这一点,那就太好了.这就是Repository的用武之地.

数据服务可以使用"哑"存储库作为可以执行复杂查询的数据源.然后,您可以通过将存储库替换为使用a List<T>作为其数据存储的虚假实现来测试数据服务.

使这种混乱的唯一原因是大量的示例显示控制器直接与存储库对话.(S#arp架构,我在看你.)如果你正在查看这些例子,并且你已经有了服务层,那么我同意这很难看出存储库的好处是什么.但是,如果你只是考虑服务层本身的测试,并且不打算让控制器直接与存储库对话,那么它开始变得更有意义.