Entity Framework 4.1 和 NHibernate 的获取策略封装

发布于 2024-11-10 01:50:28 字数 1374 浏览 5 评论 0原文

我创建了一个项目来测试 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 库的函数或注册我自己的扩展方法来满足他们的解析器的要求。

时髦。

I created a project to test out NHibernate 3+ vs. Entity Framework 4.1, wrapping it in a repository, making it very testable using interfaces etc.

I do not want to expose either ORM outside of the repositories (I do not even expose IQueryables). Everything should be handled in that layer and until I tried to handle fetching in an abstract way, everything was good.

Microsoft's implementation of adding eager loading uses either magic strings (yuck) or Linq expressions (yay) on the Include function. Their syntax follows something like this:

IQueryableThing.Include(o => o.Person);
IQueryableThing.Include(o => o.Company.Contact);
IQueryableThing.Include(o => o.Orders.Select(p => p.LineItem.Cost);

The first will just load the associated person. (parent)
The second will load the associated company and each company's contact. (parent and grandparent).
The third will load all associated orders, line items and costs for each order.

It's a pretty slick implementation.

NHibernate uses a slightly different approach. They still use Linq expressions, but they make heavier use of extension methods (fluent approach).

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);

(I'm not sure I if the third line is the correct syntax)

I can encapsulate a list of expressions in a separate class and then apply those expression to the IQueryable within that class. So what I would need to do is standardize on the Microsoft expression syntax and then translate that into NHibernate's syntax by walking the expression tree and rebuilding each expression.

This is the part that's really tricky. I have to maintain a particular order of operations in order to call the correct function for the IQueryable (must start with either Fetch or FetchMany, with each subsequent being a "ThenFetch" or "ThenFetchMany"), which stops me from using the built-in ExpressionVisitor class.

Edit:
I finally created an expression parser that will take any level of nesting of properties, collections, and selects on collections and produce an array of expressions. Unfortunately, the built in Fetch extensions methods do not take LambdaExpression as a parameter.

The part I am stuck on currently is not being able to use the built in Fetch definitions from nHibernate. It looks like I may have to hit the Remotion library's functions directly or register my own extension methods that will satisfy their parser.

Funky.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

偷得浮生 2024-11-17 01:50:28

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

Have you tried using NHiberanteUtil.Initialize()? I haven't attempted to do what you are doing, but I think Initialize will work akin to Include().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文