我正在研究MVC和EF,我经常在关于这些主题的文章中看到控制器通过Repository对象操作数据而不是直接使用LINQ to Entities。
我创建了一个小型Web应用程序来测试一些想法。它将以下接口声明为数据存储的抽象
public interface ITinyShopDataService
{
IQueryable<Category> Categories { get; }
IQueryable<Product> Products { get; }
}
然后我有一个继承自生成的类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; }
}
}
最后,控制器使用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);
}
}
我认为上面的控制器具有一些积极的属性。
因此,我认为在控制器和ObjectContext派生类之间添加Repository没有任何好处。我错过了什么? (对不起,第一篇文章有点太长了)
答案 0 :(得分:5)
您可以根据自己的建议对控制器进行测试。
但是如何在数据服务中测试您的查询?想象一下,你有非常复杂的查询行为,有多个复杂的查询来返回结果(检查安全性,然后查询Web服务,然后查询EF等)。
你可以将它放在控制器中,但这显然是错误的。
当然,它应该进入你的服务层。您可以模拟/伪造服务层以测试控制器,但现在您需要测试服务层。
如果你能在不连接数据库(或网络服务)的情况下做到这一点,那就太好了。这就是Repository的用武之地。
数据服务可以使用“哑”存储库作为可以执行复杂查询的数据源。然后,您可以使用使用List<T>
作为其数据存储的虚假实现替换存储库来测试数据服务。
唯一令这种混淆的事情是大量的示例显示控制器直接与存储库对话。 (S#arp架构,我在看你。)如果你正在查看这些例子,并且你已经有了服务层,那么我同意这很难看出存储库的好处是什么。但是如果你只考虑服务层本身的测试,并且不打算让控制器直接与存储库对话,那么它就会变得更有意义。
答案 1 :(得分:2)
NHibernate项目的Ayende和其他名气agrees with you.
某些域驱动设计人员会建议您应该从控制器调用服务(与Web服务不同),但DDD通常应用于复杂域。在简单的应用程序中,您正在做的事情很好并且可以测试。
答案 2 :(得分:0)
您缺少的是更新,创建和删除对象的能力。如果那不是问题,那么界面可能就好了(尽管我会让它从IDisposable
派生出来以确保你可以随时处理上下文(并测试它))
答案 3 :(得分:0)
存储库模式与实体框架无关,尽管实体框架实现了一个&#34;存储库&#34;图案。
存储库接口(假设IRepositoryProducts
)存在于域层中。如果您不想使用域驱动设计,它可以理解域对象,甚至是实体。
但它的实现(假设为RepositoryProducts
)是实际的存储库模式实现,并不存在于域层中,而是存在于持久层中。
此实现可以使用Entity或任何ORM ..或者不保留数据库中的信息。
所以答案是:它并不是真的必要,但建议使用Repository模式,尽管使用Entity ORM作为保持域层和持久层之间分离的良好做法。因为这是存储库模式的目的:域逻辑与信息持久化方式之间的关注点分离。当您使用域级别的存储库模式时,您只需抽象自己并思考&#34;我想存储此信息,我不关心它是如何完成的,#34;或者&#34; I想要列出这些东西,我不在乎你从哪里获取它们或者如何检索它们。请给我&#34;。
实体框架与域层无关,它只是一种很好的持久化对象的方式,但应该存在于存储库实现中(持久层)