实体框架包括Where

时间:2011-12-08 21:06:12

标签: c# entity-framework entity-framework-4.1

如果我有一个如下所示的查询:

var forms = repo.GetForms().Where(f => f.SubForms.Any(sf => sf.Classes.Any(c => c.TermId == termId)));

从这里你可以看到我的架构如下:

SubForm有许多Class,其中有许多Term

我想要的是什么:

所有SubForms及其Classes在特定的Term

现在发生的事情是,我获得了SubForm中所有Class Term的{​​{1}}。这意味着SubForm会返回所有Class,而不仅仅是与Term相关的内容。

例如。我有2个术语,每个术语有2个类的子表单。此查询返回4个类而不是该特定术语中的2个。

我可以用Include('Expression')说我只想根据条件包含所有类吗?或者我的查询错了?

5 个答案:

答案 0 :(得分:6)

使用此:

var subForms = repo.GetSubForms.Select(sf = new {
        SubForm = sf,
        Classes = sf.Classes.Where(c => c.TermId == termId)
    }).ToList()
    .Select(t => t.SubForm)
    .ToList();

更新:基于@ Slauma的评论:

如果您要加载SubFormClass Term termId var subForms = repo.Terms.Where(t => t.Id == termId).Select(t => new { Term = t, Class = t.Class, SubForm = t.Class.SubForm }).ToList() .Select(t => t.SubForm).ToList(); ,您可以从头到尾;像这样:

Include

以最简单的方式,您可以在Term上使用var subForms = repo.Terms.Include("Class.SubForm").Where(t => t.Id == termId) .Select(t => t.Class.SubForm).ToList(); ,请参阅:

SubForm has_many Class has_many Term

注意:我可以从您的问题中了解到,您有这样的关系:

SubForm has_many Class
Term has_many Class

但是,您提供的代码显示的是这样的关系:

{{1}}

如果可以,请提出您的实体,或者更多地解释他们之间的关系。谢谢。

答案 1 :(得分:4)

Include(Where Expression)不存在。如果您使用Include进行预先加载,您将始终加载所有元素。

通过使用投影可以解决这个问题。基本思想是,您将选择具有所需属性的新匿名类型,以及具有已过滤导航项的另一个属性。 EF会将这些链接在一起,因此您会伪造Include(Where ... )

Check this for an example

答案 2 :(得分:1)

你知道有时候我开始迷失在花哨的LINQ扩展方法中,并试图弄清楚如何急切地加载我想要的东西,并采用一个非常简单的“加入”概念。

var result = 
(from f in SubForums
from c in Classes
from t in Term
where t.TermId = 1
select new { SubForum = f, Class = c, Term = t }).ToList();

这是一个使用预定义导航属性的简单连接(因此您不必指定连接条件)。您将返回一个匿名类型,其中包含您需要的所有内容。这样做的好处在于Entity Framework会为您进行自动修复,因此,如果您愿意,您可以自由地从您的方法返回SubForum,它将自动包含Class和后续Term引用。

答案 3 :(得分:0)

我不知道关系的确切名称,但它应该是

的内容
repo.Terms
    .Include("Classes")
    .Include("Classes.SubForms")
    .SingleOrDefault(x => x.TermId = termId);

// or 

repo.GetSubForms
    .Include("Classes")
    .Where(sf => sf.Classes.Where(c => c.TermId == termId));

答案 4 :(得分:0)

这似乎是一个普遍的要求,当我今年早些时候看时,很难找到解决方案。我最终使用了下面链接中包含的解决方案(我不确定这是我找到的确切解决方案,但它是相同的想法)。希望这有帮助!

Filter the "Includes" table on Entity Framework query

                //Found this method to filter our child objects instead of using .include()
                var Results = (from res in
                                   (from u in DataContext.User
                                    where u.Type.ToUpper() != "ADMIN"
                                    && u.StartDate <= DateTime.Now
                                    && (u.EndDate == null || u.EndDate >= DateTime.Now)
                                    select new
                                    {
                                        User = u,
                                        Access = u.Access.Where(a => a.StartDate <= DateTime.Now
                                                  && (a.EndDate == null || a.EndDate >= DateTime.Now))
                                    }
                                    )
                               select res);

                //The ToArray is neccesary otherwise the Access is not populated in the Users
                ReturnValue = Results.ToArray().Select(x => x.User).ToList();