我创建了一个项目来测试NHibernate 3+与Entity Framework 4.1,将它包装在一个存储库中,使用接口等使其非常可测试。
我不想在存储库之外暴露任何ORM(我甚至不公开IQueryables)。一切都应该在那一层处理,直到我试图以抽象的方式处理抓取,一切都很好。
Microsoft添加预先加载的实现在Include函数上使用魔术字符串(yuck)或Linq表达式(yay)。他们的语法如下:
IQueryableThing.Include(o => o.Person);
IQueryableThing.Include(o => o.Company.Contact);
IQueryableThing.Include(o => o.Orders.Select(p => p.LineItem.Cost);
第一个只会加载相关人员。 (父) 第二个将加载关联公司和每个公司的联系人。 (父母和祖父母)。 第三个将加载每个订单的所有相关订单,订单项和费用。
这是一个非常漂亮的实现。
NHibernate采用略有不同的方法。他们仍然使用Linq表达式,但他们更多地使用扩展方法(流畅的方法)。
IQueryableThing.Fetch(o => o.Person);
IQueryableThing.Fetch(o => o.Company).ThenFetch(o => o.Contact);
IQueryableThing.FetchMany(o => o.Orders).ThenFetch(p => p.LineItem).ThenFetch(q => q.Cost);
(我不确定我的第三行是否是正确的语法)
我可以在单独的类中封装表达式列表,然后将这些表达式应用于该类中的IQueryable。所以我需要做的是标准化Microsoft表达式语法,然后通过遍历表达式树并重建每个表达式将其转换为NHibernate的语法。
这是非常棘手的部分。我必须维护一个特定的操作顺序,以便为IQueryable调用正确的函数(必须以Fetch或FetchMany开头,随后每个都是“ThenFetch”或“ThenFetchMany”),这阻止我使用内置函数在ExpressionVisitor类中。
编辑: 我最终创建了一个表达式解析器,它将对集合中的属性,集合和选择进行任何级别的嵌套,并生成表达式数组。不幸的是,内置的Fetch扩展方法不会将LambdaExpression作为参数。
我目前停留的部分无法使用nHibernate内置的Fetch定义。看起来我可能需要直接点击Remotion库的函数或者注册我自己的扩展方法来满足它们的解析器。
时髦。
答案 0 :(得分:0)
您是否尝试过使用NHiberanteUtil.Initialize()
?我没有尝试过你正在做的事情,但我认为Initialize的工作方式类似于Include()
。