我创建了一个项目来测试 NHibernate 3+ 与 Entity Framework 4.1,将其包装在存储库中,使其非常易于使用接口(interface)等进行测试。

我不想在存储库之外公开任何一个 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); 

第一个只会加载关联的人。 ( parent ) 第二个将加载关联公司和每个公司的联系人。 ( parent 和祖 parent )。 第三个将加载所有关联的订单、行项目和每个订单的成本。

这是一个非常巧妙的实现。

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 库的函数或注册我自己的扩展方法来满足它们的解析器。

时髦。

请您参考如下方法:

您是否尝试过使用 NHiberanteUtil.Initialize()?我没有尝试做你正在做的事情,但我认为 Initialize 的工作方式类似于 Include()。


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!