Entity Framework 4.1 和 NHibernate 的获取策略封装
Posted
技术标签:
【中文标题】Entity Framework 4.1 和 NHibernate 的获取策略封装【英文标题】:Fetching strategy encapsulation for Entity Framework 4.1 and NHibernate 【发布时间】:2011-09-02 17:15:17 【问题描述】:我创建了一个项目来测试 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 库的函数,或者注册我自己的扩展方法来满足他们的解析器。
时髦。
【问题讨论】:
【参考方案1】:您是否尝试过使用NHiberanteUtil.Initialize()
?我没有尝试做你正在做的事情,但我认为 Initialize 将类似于Include()
。
【讨论】:
我想公开一种在持久层之外应用即时加载的方法,而不公开 ORM 本身的细节。所以我正在使用 Linq 表达式,需要解析 Linq 表达式并将它们提供给 nHibernate 的 fetch 方法。请进一步解释 Initialize 是如何解决这个问题的,因为我没有看到它。 @junkyspace 好吧,我实际上并不确定它会解决它,但 Initialize 接受类似NHibernateUtil.Initialize(IQueryableThing.Fetch(o=>o.Company.Contact))
的东西。我的想法是你会使用相同的表达方式。
@junkyspace 没关系。我的建议运行,但实际上并没有做急切的负载。如果我尝试强制使用 FirstOfDefault(),Fetch() 会抛出异常 - 表达式太复杂。
感谢您的尝试 :) 我遇到了同样的问题,只是在 fetch 中指定了它。我现在用父母/祖父母关系(o => o.parent1.parent1)解决了一半,但剖析一对多(parent.collection.select(o => o.something))表达式是有点棘手。以上是关于Entity Framework 4.1 和 NHibernate 的获取策略封装的主要内容,如果未能解决你的问题,请参考以下文章
卸载 Entity Framework 4.1 六月 CTP
Entity Framework 4.1 DbContext API 中的接口和存储库抽象中断子查询?
如何在 Entity Framework 4.1 中使用更新 SPROC