Entity Framework中的Include和Select如何一起使用

15

我有以下实体(伪代码以节省空间)

Program [ int Id, 
          string Name, 
          List<ProgramFoodType> ProgramFoodTypes, 
          List<ProgramFood> ProgramFoods]

ProgramFoodType[ int Id, int ProgramId, int Type, bool IsActive]
ProgramFood [ int Id, int ProgramId, Food Food, FoodType FoodType]
Food [int Id, string Name]
FoodType [int Id, string Name]

我的任务是获取单个带有相关联的ProgramFoodTypes的Program,其中ProgramFoodType应该是活动的,并且还需要与相关实体Food和FoodType的ProgramFoods一起使用。 到目前为止,我已经使用了以下内容: 1- 下面的查询将检索ProgramFoodTypes和ProgramFoods的详细信息,但它会带来所有活动和非活动的ProgramFoodTypes。
var program = mEntities.Programs
                          .Include(p =>p.ProgramFoodTypes)
                          .Include(p =>p.ProgramFoods.Select(f =>f.Food))
                          .InClude(p =>p.ProgramFoods.Select( f =>f.FoodType))
                          .Where(m =>m.Id== Id);

2- 以下查询将检索详细信息,但缺少FoodFoodType

var program = (from p in mEntities.Programs
              where p.Id ==Id
              select new {
                 Program = p,
                 ProgramFoodTypes = from pf in p.ProgramFoodTypes
                                    where pf.IsActive
                                    select pf,                  
                 ProgramFoods = p.ProgramFoods // here i can't add include statement
              }).ToArray().Select(m => m.Program);

如何在第二个查询中包含食物和食品类型?
3个回答

4
对于您的第二个解决方案,我认为您可以使用:
var program = (from p in mEntities.Programs
                  .Include(p => p.ProgramFoods.Select(f => f.Food))
                  .Include(p => p.ProgramFoods.Select(f => f.FoodType))
               where p.Id == Id
               select new {
                  Program = p,
                  ProgramFoodTypes = from pf in p.ProgramFoodTypes
                                     where pf.IsActive
                                     select pf,                  
                  p.ProgramFoods 
               }).ToArray().Select(m => m.Program);
更新:由于您在Linq查询中使用了匿名类型,所以包含语句被忽略
您需要在客户端加载所有相关的ProgramFoodTypes,然后进行过滤。
var program = mEntities.Programs
                   .Include(p => p.ProgramFoodTypes)
                   .Include(p => p.ProgramFoods.Select(f => f.Food))
                   .Include(p => p.ProgramFoods.Select(f => f.FoodType))
                   .SingleOrDefault(m => m.Id == Id);

program.ProgramFoodTypes = program.ProgramFoodTypes.Where(pft => pft.IsActive);  

如果你希望确保数据在数据库端不被改变,可以使用 AsNoTracking() 或将返回的 Program 对象克隆到一个新对象中。


结果中的Food和FoodType仍然为空。 - Monah
啊,我明白了。那是因为你选择了匿名对象而不是实体本身。我正在更新我的答案... - Kamyar
我试图避免拆分查询并使其简单化,缺失的部分是我可以在匿名子查询中包含食物和食品类型,正如@tschmit007在他的答案中提到的那样,感谢您的更新,我认为它会起作用,因为它已经被拆分了。 - Monah

3

可能是:

var program = (from p in mEntities.Programs
          where p.Id ==Id
          select new {
             Program = p,
             ProgramFoodTypes = from pf in p.ProgramFoodTypes
                                where pf.IsActive
                                select pf,                  
             ProgramFoods = p.ProgramFoods.Select(y => new {
                 Food = y.Food,
                 Type = y.FoodType
             }) 
          }).ToArray().Select(m => m.Program);

它运行得很好,只是我添加了ProgramFood本身,否则它将无法检索,谢谢。 - Monah

0

试试这个:

var program = mEntities.Programs
                       .Include(p => p.ProgramFoodTypes)
                       .Include(p => p.ProgramFoods.Select(f => f.Food))
                       .InClude(p => p.ProgramFoods.Select(f => f.FoodType))
                       .SingleOrDefault(m => m.Id == Id && m.ProgramFoodTypes.All(t => t.IsActive));

它返回了 System.NullReferenceException(对象引用未设置为对象的实例)。 - Monah
如果您的意思是program为空,那是因为没有找到符合条件的结果。 - haim770
我认为OP想要实现的是获取对象,但仅与其IsActive设置为true的ProgramFoodTypes相关。 - Kamyar
我通常可以获得结果,但当我删除 m.ProgramFoodTypes.All(t=>t.IsActive) 时,我得到的不是我想要的。似乎 where 子句在实际包含实体之前就已经应用了?就像这样。 - Monah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接