Vic*_*ues 69 c# entity-framework visual-studio-2008
我有一个Item
.Item
有一个Category
.
Category
有ID
,Name
,Parent
和Children
.Parent
和Children
是Category
太.
当我为特定的LINQ to Entities查询时Item
,它不返回相关的Category
,除非我使用该Include("Category")
方法.但它并没有带来父母和孩子的完整范畴.我能做到Include("Category.Parent")
,但这个对象就像一棵树,我有一个递归的层次结构,我不知道它的结束.
如何让EF完全加载Category
父项和子项,父项与父项和子项一起加载,依此类推?
这不适用于整个应用程序,出于性能考虑,仅需要此特定实体(类别).
Shi*_*iji 22
而不是使用Include
您可以使用的方法Load
.
然后你可以为每个人做一个并循环所有的孩子,加载他们的孩子.然后通过他们的孩子为每个人做一个,等等.
你所经历的等级数将被硬编码为你拥有的每个循环的数量.
以下是使用的示例Load
:http://msdn.microsoft.com/en-us/library/bb896249.aspx
Ale*_*mes 14
如果你肯定想要加载整个层次结构,那么如果是我,我会尝试编写一个存储过程,它的工作就是返回层次结构中的所有项目,返回你首先要求的那个(以及随后的子项).
然后让EF的关系修复确保它们都被连接起来.
即:像:
// the GetCategoryAndHierarchyById method is an enum
Category c = ctx.GetCategoryAndHierarchyById(1).ToList().First();
Run Code Online (Sandbox Code Playgroud)
如果您已正确编写存储过程,则实现层次结构中的所有项目(即ToList()
)将使EF关系修复启动.
然后你想要的项目(First())应该加载它的所有子项,并且应该加载它们的子项等.所有这些都是从那个存储过程调用填充的,所以也没有MARS问题.
希望这可以帮助
亚历克斯
如果您碰巧加载了所有递归实体,尤其是在类别上,可能会很危险,最终可能会比您讨价还价更多:
Category > Item > OrderLine > Item
OrderHeader > OrderLine > Item
> Item > ...
Run Code Online (Sandbox Code Playgroud)
你突然加载了大部分数据库,你也可以加载发票行,然后是客户,然后加载所有其他发票.
你应该做的是如下:
var qryCategories = from q in ctx.Categories
where q.Status == "Open"
select q;
foreach (Category cat in qryCategories) {
if (!cat.Items.IsLoaded)
cat.Items.Load();
// This will only load product groups "once" if need be.
if (!cat.ProductGroupReference.IsLoaded)
cat.ProductGroupReference.Load();
foreach (Item item in cat.Items) {
// product group and items are guaranteed
// to be loaded if you use them here.
}
}
Run Code Online (Sandbox Code Playgroud)
但是,更好的解决方案是构建查询以使用结果构建匿名类,这样您只需要访问一次数据存储区.
var qryCategories = from q in ctx.Categories
where q.Status == "Open"
select new {
Category = q,
ProductGroup = q.ProductGroup,
Items = q.Items
};
Run Code Online (Sandbox Code Playgroud)
这样,您可以根据需要返回字典结果.
请记住,您的情境应该尽可能短暂.
使用这种调用 的硬编码版本的扩展方法Include
来实现包含的动态深度级别,效果很好。
namespace System.Data.Entity
{
using Linq;
using Linq.Expressions;
using Text;
public static class QueryableExtensions
{
public static IQueryable<TEntity> Include<TEntity>(this IQueryable<TEntity> source,
int levelIndex, Expression<Func<TEntity, TEntity>> expression)
{
if (levelIndex < 0)
throw new ArgumentOutOfRangeException(nameof(levelIndex));
var member = (MemberExpression)expression.Body;
var property = member.Member.Name;
var sb = new StringBuilder();
for (int i = 0; i < levelIndex; i++)
{
if (i > 0)
sb.Append(Type.Delimiter);
sb.Append(property);
}
return source.Include(sb.ToString());
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var affiliate = await DbContext.Affiliates
.Include(3, a => a.Referrer)
.SingleOrDefaultAsync(a => a.Id == affiliateId);
Run Code Online (Sandbox Code Playgroud)
无论如何,同时,在 EF 回购中加入有关它的讨论。