从Entity Framework .NET返回父项子女的多个孙子

时间:2017-10-20 19:45:39

标签: c# asp.net .net entity-framework-6 visual-studio-2017

我正在使用VS2017来创建ASP.NET Web应用程序(不使用CORE),.NET Framework是4.6.2,实体框架.NET是6.1.3。我已经在这里查看了我的答案,但是我所尝试的或我提到的所有内容都无法使用。

我现在有以下代码来获得特定父母的孩子的孙子孙女,我知道必须有一种更有效的方式来获得这些孙子孙女,但无法弄清楚如何:

            using (_ge = new generation_entities())
        {
            if (_id != null)
            {
                List<scheduleheader> _tlist = (from a in _ge.scheduleheaders.Include("scheduledetails") where a.programID == _id select a).ToList();
                foreach (scheduleheader _t in _tlist)
                {
                    foreach (scheduledetail _s in _t.scheduledetails)
                    {
                        _s.scheddtlcustoms = (from a in _ge.scheddtlcustoms where a.dtlID == _s.dtlID select a).ToList();
                        _s.scheddtlstandards = (from a in _ge.scheddtlstandards where a.dtlID == _s.dtlID select a).ToList();
                        _s.scheddtltalks = (from a in _ge.scheddtltalks where a.dtlID == _s.dtlID select a).ToList();
                        _s.scheddtlvenues = (from a in _ge.scheddtlvenues where a.dtlID == _s.dtlID select a).ToList();
                        _s.scheduledtlrecurrences = (from a in _ge.scheduledtlrecurrences where a.dtlID == _s.dtlID select a).ToList();
                    }
                }
                return _tlist;
            }
            else
                return (from a in _ge.scheduleheaders where a.scheduledetails.Any(b => b.start > DateTime.Today.AddDays(-30)) && a.programID == null select a).ToList();
        }

我已尝试使用.ThenIncludeInclude("xxxx.xxxx.xxxx")但是.ThenInclude甚至不可用,而Include("xxxx.xxxx.xxxx")仅适用于一个孙子。 Include()只允许我输入一个字符串路径,但我已经看到OP使用旧版EF的评论。

我坚持这一点,如果我在这里错过了什么,我可以开悟吗?

2 个答案:

答案 0 :(得分:2)

您可以尝试以下方式:

            var query = context
                    .Parents
                    .Include(p=>p.children)
                    .Include(p=>p.children.Select(x=>x.Grandchild1))
                    .Include(p=>p.children.Select(x=>x.Grandchild2))
                    .ToList();

您可以使用linq访问此内容,您可能有一个ID,您可以执行以下操作:

var grandchild6 = query
                   .children
                  .FirstOrDefault(child=>child.Id =1)
                 ?.GranChildern
                 ?.FirstOrDefault(grandChild=>grandchild.Id = 6);

答案 1 :(得分:1)

您可以按照另一个答案中的指示链接多个Include("xxxx.xxxx.xxxx")

但是,这将用单个但是怪物SQL查询替换当前parents.Count * children.Count * grandChildrenTypes.Count个SQL查询的数量,这些查询合并了单个结果集中的所有列和所有记录,这可能也不高效。

我建议你采用混合方法(类似于EF Core处理Include的方式),每个父母执行1个SQL,每个孩子1个,每个孙子1个类型 ,即在这种特殊情况下共有7个SQL查询。只有父查询结果存储在变量中,子孙查询才刚刚执行,整个脏工作由EF导航属性修复完成:

// Load parents
var parentQuery = _ge.scheduleheaders.Where(a => a.programID == _id);
var parents = parentQuery.ToList();
// Load children
var childQuery = parentQuery.SelectMany(p => p.scheduledetails);
childQuery.Load();
// Load grandchildren
childQuery.SelectMany(c => c.scheddtlcustoms).Load();
childQuery.SelectMany(c => c.scheddtlstandards).Load();
childQuery.SelectMany(c => c.scheddtltalks).Load();
childQuery.SelectMany(c => c.scheddtlvenues).Load();
childQuery.SelectMany(c => c.scheduledtlrecurrences).Load();
// Done
return parents;