简体   繁体   English

实体框架包括Where

[英]Entity Framework include Where

If I have a query that looks like this: 如果我有一个如下所示的查询:

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

From this you can see my schema is as follows: 从这里你可以看到我的架构如下:

SubForm has many Class which has many Term . SubForm有许多具有多个Term Class

What I want: 我想要的是:

All SubForms with their Classes In a particular Term . 所有SubForms及其在特定TermClasses

What is happening now is that I get all the SubForm that has any Class in a particular Term . 现在发生的事情是我获得了在特定Term中具有任何Class所有SubForm That means that SubForm comes back with ALL child Class and not just the ones related to the Term . 这意味着SubForm会返回所有Class ,而不仅仅是与Term相关的子Class

For eg. 例如。 I have 2 terms, a subform with 2 classes in each term. 我有2个术语,每个术语有2个类的子表单。 This query brings back 4 classes instead of the 2 in that particular term. 此查询返回4个类而不是该特定术语中的2个类。

Is there any Include('Expression') that I can use to say that I only want to include all classes based on a condition? 是否有任何Include('Expression')可以用来表示我只想根据条件包含所有类? Or is my query wrong? 或者我的查询错了?

Use this: 用这个:

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

UPDATE: based on @Slauma's comment: 更新:根据@ Slauma的评论:

If you want to load SubForm s that they have any Class that has a Term by termId , you can go from end to begin; 如果要加载SubForm s表示他们有任何Class ,有一个TermtermId ,你可以从去年底开始, like this: 像这样:

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

OR in a easiest way, you can use Include on your Term , see: 或者以最简单的方式,您可以在您的Term上使用Include ,请参阅:

var subForms = repo.Terms.Include("Class.SubForm").Where(t => t.Id == termId)
                   .Select(t => t.Class.SubForm).ToList();

NOTE: As I can understand from your question, you have a relationship like this: 注意:正如我从您的问题中可以理解的那样,您有这样的关系:

SubForm has_many Class has_many Term

But, your provided code is showing a relationship like this one: 但是,您提供的代码显示的是这样的关系:

SubForm has_many Class
Term has_many Class

If you can, put your entities in question, or explain their relationship more please. 如果可以的话,请提出您的实体,或者更多地解释他们之间的关系。 Thank you. 谢谢。

An Include(Where Expression) does not exist. Include(Where Expression)不存在。 If you use eager loading with Include you will always load all the elements. 如果您使用Include进行预先加载,您将始终加载所有元素。

There is a way around this by using projections. 通过使用投影可以解决这个问题。 The basic idea is you will select a new anonymous type with the property you want and another property with the filtered navigational items. 基本思想是,您将选择具有所需属性的新匿名类型,以及具有已过滤导航项的另一个属性。 EF will link those together and as a result you will fake a Include(Where ... ) EF将这些链接在一起,因此你会伪造一个Include(Where ... )

Check this for an example . 请查看此示例

You know sometimes I start getting lost in fancy LINQ extension methods and attempting to figure out how to eagerly load exactly what I want and resort to a very simple "join" concept. 你知道有时候我开始迷失在花哨的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();

This is a simple join that uses predefined navigation properties (hence you don't have to specify the join condition). 这是一个使用预定义导航属性的简单连接(因此您不必指定连接条件)。 You return an anonymous type with everything that you need. 您将返回一个匿名类型,其中包含您需要的所有内容。 The beauty of this is that Entity Framework will do the auto-fixup for you, therefor you're free to return the SubForum only from your method if you wish, it will automatically contain the Class and subsequent Term references. 这样做的好处在于Entity Framework会为您进行自动修复,因此,如果您愿意,您可以自由地从您的方法返回SubForum,它将自动包含Class和后续Term引用。

I don't know the exact names of the relations, but it should be something along the lines of 我不知道这些关系的确切名称,但它应该是符合的

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

This seems to be a common request, it was difficult to find a solution to it when I was looking earlier this year. 这似乎是一个普遍的要求,当我今年早些时候看时,很难找到解决方案。 I ended up using the solution included in the link below (I'm not sure this is the exact solution I found, but it's the same idea). 我最终使用了下面链接中包含的解决方案(我不确定这是我找到的确切解决方案,但它是相同的想法)。 Hope this helps! 希望这可以帮助!

Filter the "Includes" table on Entity Framework query 过滤Entity Framework查询中的“包含”表

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM