实体框架 - 预加载相关实体
我正在将 Entity Framework 4 与 MVC 一起使用,并且需要确保在控制器方法返回之前已加载我想要在视图中使用的任何引用实体,否则视图会抛出可怕的内容:
ObjectContext 实例已被释放,不能再用于需要连接的操作。
直接从上下文中选择时,我可以使用 Include(string)
方法强制将它们包含在生成的 SQL 查询中:
var sellers = context.Sellers.Include("Recommendations.User").ToList();
但是,如果我(例如)有一个接受的辅助方法一个实体并需要加载所有项目,但没有可用的 Include
方法。
void Test(Seller seller)
{
// ensure all recommendations and their users are loaded
}
强力方法是循环遍历它们:
foreach (var recommendation in seller.Recommendations)
recommendation.User.ToString(); // just force a load
如果我有 100 个建议,这将在幕后创建 101 个 SQL 查询。理想情况下,我想要一种方法/途径,只需一次 SQL 访问即可加载所有 Recommendation
和 User
对象。
给我看看钱。
编辑 我不太有兴趣讨论这是一个好还是坏的架构。为了这个问题,我简化了我的场景。你能用 EF API 完成我的要求吗?
编辑2
Ladislav的编辑提供希望有一种新的方法,但似乎我还没有完全实现。
我可以通过以下方式实现我想要的:
context.Sellers.Include("Recommendations.User").Single(s => s.Id == seller.Id);
此方法无法使用 LoadProperty
...
context.LoadProperty(seller, "Recommendations.User");
...因为它失败并出现错误...
找不到指定的导航属性Recommendations.User。
如果您没有对上下文的引用,这些方法都不起作用。
I'm using Entity Framework 4 with MVC and need to ensure any referenced entities I want to use in my view have been loaded before the controller method returns, otherwise the view spits out the dreaded:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
When selecting straight from the context, I can just use the Include(string)
method to force them to be included in the generated SQL query:
var sellers = context.Sellers.Include("Recommendations.User").ToList();
However, if I have (for example) a helper method that accepts an entity and needs all items to be loaded, there's no Include
method available.
void Test(Seller seller)
{
// ensure all recommendations and their users are loaded
}
The brute force approach is to loop through them:
foreach (var recommendation in seller.Recommendations)
recommendation.User.ToString(); // just force a load
If I have 100 recommendations, this will create 101 SQL queries behind-the-scenes. Ideally I want a method/approach that loads all Recommendation
AND User
objects with only a single trip to SQL.
Show me the money.
EDIT I'm not really interested in discussing whether this is a good or bad architecture. I've simplified my scenario for the sake of the question. Can you do what I'm asking with the EF API?
EDIT 2
Ladislav's edit offered hope of a new approach, but it seems I'm not quite there.
I can achieve what I want via this:
context.Sellers.Include("Recommendations.User").Single(s => s.Id == seller.Id);
This approach doesn't work using LoadProperty
...
context.LoadProperty(seller, "Recommendations.User");
...as it fails with the error...
The specified navigation property Recommendations.User could not be found.
Neither of these approaches work if you don't have a reference to the context.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是一个老问题,但在 EF6 中,您可以完成在实体上加载依赖对象,例如 this:
这将加载给定
卖家
的所有推荐
及其相关用户
This is an old question, but in EF6 you can accomplish loading dependent objects on an entity like this:
That would load all
Recommendations
and their relatedUsers
for the givenseller
我认为这是您的存储库的一项工作,在您的情况下,它应该公开诸如 GetFullSeller (由 Include 加载的所有属性)和 GetSeller (仅基本实体)之类的方法。
编辑:
有多种方法可以在 EF v4 中加载导航属性。
没有自动加载。
I think this is a job for your repository which should in your case expose methods like GetFullSeller (all properties loaded by Include) and GetSeller (only base entity).
Edit:
There are several ways how to load navigation properties in EF v4.
There is no automatic loading.
我也有同样的情况。我认为使用EF很容易陷入101查询问题。
解决方案可以是创建 Seller 类的分部类(由 EF 生成)并实现返回 IQueryable 的 GetSubclassNameQ 和返回带有预加载的 IQueryable 的 GetSubclassNameQFull。
I'm in the same situation. I think that with EF is very easy to fall in a 101 query problem.
A solution can be to create a partial class of your Seller class (generated by EF) and implement a GetSubclassNameQ that return a IQueryable, and a GetSubclassNameQFull that return a IQueryable with eager loading.
您可能希望使用控制器将它们映射到模型对象中,而不是将实际的域对象 (EntityObject) 传递给视图,以更好地表示视图实际应显示的内容。这将减少视图中所需的逻辑量,并具有避免在上下文过期后传递 EntityObject 的令人愉快的副作用。
根据您的编辑进行编辑:
不,API 无法获取单个实体对象并创建其类型的所有其他实体对象(该对象在加载时会同时加载) -一下子就填充了特定的财产。您最好首先使用“包含”提及来拉出所有项目,就像您在问题中所示的那样。
Rather than passing your actual domain objects (
EntityObject
s) to the view, you may want to use your controller to map them into a Model object that better represents what your view should actually be displaying. This will reduce the amount of logic required in your View, and have the pleasant side-effect of avoiding passing EntityObjects around after their context has expired.Edit based on your edit:
No, the API doesn't have a way to take a single Entity Object and make every other Entity Object of its type which was loaded at the same time it was be lazy-populated with a particular property in one fell swoop. You are better off pulling all of the items out in the first place using the
Include
mention like you show in your question.