如何通过外观层设置 NHibernate Linq 获取策略
我使用 NHibernate 进行数据访问,但通过外观层访问它。该层由存储库的接口以及对应于 ISession 对象的 IUnitOfWork 接口组成。
为了正确管理检索到的实体,存储库在其构造函数中传递 IUnitOfWork,并使用 IUnitOfWork 进行加载。
IUnitOfWork 包含一个名为 All 的属性,该属性以 IQueryable 的形式检索该类的所有实体(用于以后的过滤)。因此,检索今年创建的所有实体的存储库方法可能如下所示:
注意:这不是这些接口和类的完整代码!只有与我的问题相关的代码。
IUnitOfWork 接口:
IQueryable<T> GetList<T>();
UnitOfWork 具体类:
public IQueryable<T> GetList<T>()
{
return _session.Linq<T>();
}
IFooRepository 接口
IQueryable<Foo> All { get; }
IEnumerable<Foo> ThisYearsFoos{ get; }
FooRepository 具体类
public IQueryable<Foo> All
{
get { return _unitOfWork.GetList<Foo>(); }
}
public IEnumerable<Foo> ThisYearsFoos
{
get { return All.Where(x => x.DateCreated > new DateTime(2010,1,1);}
}
我想添加功能来指定获取策略以便可以快速加载相关实体。假设 Foo 有一个对应于另一个实体 Bar 的属性:
public class Foo
{
public Bar {get;set;}
}
映射文件指定 Bar 是延迟加载的,但在我的 ThisYearsFoos 存储库属性中,我想指定 Bar 应立即加载以避免 N+1 选择。
在 Linq to NHibernate 中,我们可以使用 Expand() 扩展方法指定急切获取。然而,这个扩展方法属于NHibernateQueryable类型,而IUnitOfWork接口的GetList方法只知道IQueryable。
显然,我不希望 IUnitOfWork 接口了解 INHibernateQueryable,因为它应该不了解 NHibernate。
使用我上面指定的设计,有没有一种我想不到的方法可以做到这一点?或者我的设计需要重新思考吗?
谢谢
大卫
I’m using NHibernate for data access, but accessing it through a façade layer. This layer consists of interfaces for the repositories, plus an IUnitOfWork interface which corresponds to the ISession object.
In order that retrieved entities are managed correctly, repositories are passed an IUnitOfWork in their constructor and the IUnitOfWork is used for the loading.
The IUnitOfWork contains a property called All, which retrieves all entities of the class as an IQueryable (for later filtering). Thus, a repository method to retrieve all entities created this year might look like the following:
NB: this is not the complete code for these interfaces and classes! Only the code relevant to my question.
IUnitOfWork interface:
IQueryable<T> GetList<T>();
UnitOfWork concrete class:
public IQueryable<T> GetList<T>()
{
return _session.Linq<T>();
}
IFooRepository interface
IQueryable<Foo> All { get; }
IEnumerable<Foo> ThisYearsFoos{ get; }
FooRepository concrete class
public IQueryable<Foo> All
{
get { return _unitOfWork.GetList<Foo>(); }
}
public IEnumerable<Foo> ThisYearsFoos
{
get { return All.Where(x => x.DateCreated > new DateTime(2010,1,1);}
}
I would like to add functionality to specify fetch strategies so that related entities can be eagerly loaded. So let’s say Foo has a property corresponding to another entity, Bar:
public class Foo
{
public Bar {get;set;}
}
The mapping file specifies that Bar is lazy-loaded, but in my ThisYearsFoos repository property I would like to specify that Bar should be eagerly loaded to avoid N+1 selects.
In Linq to NHibernate we can specify eager fetching using the Expand() extension method. However, this extension method belongs to the NHibernateQueryable type, whereas the IUnitOfWork interface’s GetList method only knows about IQueryable.
Clearly I don’t want the IUnitOfWork interface to know about INHibernateQueryable since it is supposed to not know about NHibernate.
Using the design I have specified above, is there a way to do this that I haven’t been able to think of? Or is my design in need of a rethink?
Thanks
David
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
升级到 NHibernate 3.x。与 Expand (
Fetch
) 相对应的新方法在 IQueryable 上运行。Upgrade to NHibernate 3.x. The new method that corresponds to Expand (
Fetch
) operates on IQueryable.你说的是一些相互矛盾的事情:
- 你不想暴露接口
- 你想使用那个接口
那是不可能的。你必须重新考虑你的设计。
您使用“工作单元”一词来表示与大多数人不同的事物。
大多数人期望工作单元接口具有 Commit 和 RollBack 方法,但不具有某些 IQueryable。
You are saying some conflicting things:
- You don't want to expose interface
- You want to use the use that interface
That is impossible. You have to rethink your design.
You use the term unit of work for a different thing than most people do.
Most people would expect a unit of work interface to have the methods Commit and RollBack, but not some IQueryable.