我想我在绕圈子。
我正在使用 EF4 和 POCO(数据库优先)和 IoC 开发 MVC 3 解决方案。我的存储库和 UoW 模式大多来自 this article和 this article .
我的解决方案由以下项目组成:
实现:
接口(interface):
最后,将一切联系在一起的 IoC 项目。
如果您在第一篇文章中注意到,作者提到从域服务中删除对 ObjectSet 的依赖。我假设这是为了可测试性。但是,问题在于它阻碍了从域服务执行复杂查询的能力,因为 IObjectSet 和 IEnumerable(由存储库上的大多数方法返回)不会为复杂查询保留方法。
这是否意味着我应该在我的存储库中进行复杂的查询?我应该放弃像
public T Single(Expression<Func<T, bool>> where)
这样的方法吗?并坚持使用 public T GetUserById(int id)
之类的方法?如果不是这种情况,那么我该如何做复杂的查询 such as this在我的服务层?
看看我上面的解决方案大纲和我的问题,我是在朝着正确的方向前进,还是在为自己制造问题?
提前致谢。
最佳答案
这是主观/意见问题,但您可以让您的存储库返回 IQueryable<T>
,那么您可以像这样在您的服务中执行“复杂查询”:
return _repository // IRepository<T>
.Find() // IQueryable<T>
.Where(someComplexPredicate) // IQueryable<T>
.SingleOrDefault(); // T
ObjectSet<T>
: IQueryable<T>
,这使得这成为可能。如果你想开始做
ObjectSet<T>
- 您服务中的特定内容,您有两种选择:ObjectSet<T>
-特定方法作为存储库接口(interface)上的方法IQueryable<T>
对 ObjectSet<T>
进行“软转换”的扩展方法(例如 var objSet = source as ObjectSet<T>
)。 始终尝试使用选项 1。
完美的例子是急切加载。有一种方法叫做
Include
在 ObjectContext<T>
, 所以如果你使用 IQuerayable<T>
在您的存储库中,您如何急切加载?由于
Include
需要一个“魔术字符串”,您可以在 Find
中接受它存储库中的方法,例如:return _repository // IRepository<T>
.Find("Product.Orders") // IQueryable<T>
.Where(someComplexPredicate) // IQueryable<T>
.SingleOrDefault(); // T
幸运的是,他们在 EF CTP5 中引入了强类型
Include
有效IQueryable<T>
,所以我在切换时不必执行上述操作。所以正如我所说,最好的办法是在你的 Repository 接口(interface)上公开方法。但是需要进行权衡 - 接口(interface)应该是服务的“契约(Contract)”或“定义”,而不是实现。所以 EF 特定的事情应该通过扩展方法来完成。一般的事情可以通过存储库接口(interface)完成。
关于entity-framework - 使用 DDD 和 IoC 为 EF4 实现存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5241377/