Jer*_*ose 5 domain-driven-design entity-framework repository inversion-of-control entity-framework-4
我想我是在圈子里.
我正在使用EF4和POCO(数据库优先)和IoC开发MVC 3解决方案.我的存储库和UoW模式主要是从本文和本文中采用的.
我的解决方案由以下项目组成:
实现:
接口:
最后,IoC项目将所有内容联系在一起.
如果您在第一篇文章中注意到,作者提到从域服务中删除对ObjectSet的依赖.我假设这是为了可测试性.但问题是,它阻碍了从域服务执行复杂查询的能力,因为IObjectSet和IEnumerable(由存储库上的大多数方法返回)不存在复杂查询的方法.
这是否意味着我应该在我的存储库中进行复杂的查询?我是否应该放弃类似的方法public T Single(Expression<Func<T, bool>> where)并坚持使用类似的方法public T GetUserById(int id)?
如果不是这种情况,那么如何在我的服务层中执行此类复杂查询?
看看上面的解决方案大纲和我遇到的问题,我是朝着正确的方向前进,还是我为自己创造了问题?
提前致谢.
这是主观的/意见问题,但您可以让您的存储库返回IQueryable<T>,然后您可以在您的服务中执行这样的"复杂查询":
return _repository // IRepository<T>
.Find() // IQueryable<T>
.Where(someComplexPredicate) // IQueryable<T>
.SingleOrDefault(); // T
Run Code Online (Sandbox Code Playgroud)
ObjectSet<T>:IQueryable<T>,这使得这成为可能.
如果您想ObjectSet<T>在服务中开始做特定的事情,您有两个选择:
ObjectSet<T>-specific方法公开为Repository接口上的方法IQueryable<T>扩展方法对ObjectSet<T>(例如var objSet = source as ObjectSet<T>)进行"软转换" .总是尝试选择1.
完美的例子是渴望加载.有一个名为方法Include上ObjectContext<T>,因此,如果您使用IQuerayable<T>在你的仓库,你怎么了渴望负荷?
因为Include需要一个"魔术字符串",你可以Find在你的Repository 中的方法中接受这个,例如:
return _repository // IRepository<T>
.Find("Product.Orders") // IQueryable<T>
.Where(someComplexPredicate) // IQueryable<T>
.SingleOrDefault(); // T
Run Code Online (Sandbox Code Playgroud)
幸运的是EF CTP5他们已经推出了一个强类型Include,其工作过IQueryable<T>,所以我没有当我割接做以上.
正如我所说,最好的办法是在Repository接口上公开方法.但需要进行权衡 - 界面应该是服务的"合同"或"定义",而不是关于实施.因此EF特定的事情应该通过扩展方法完成.一般事情可以通过存储库界面完成.