【问题标题】:Fetch Entity Framework objects with partially loaded collections使用部分加载的集合获取实体框架对象
【发布时间】:2013-10-03 05:33:40
【问题描述】:

我有一个具有以下内容的实体框架模型:

class Farm{
    string owner;
    List<Animal> animals;
    DateTime StartDate;
}

class Animal{
    string Name;
    DateTime DOB;
}

问题:

我想选择一个农场集合,其开始日期 >= 2013/01/01 连同它的动物,但也过滤强> 出生日期 >= 2013/06/01。

我尝试了以下方法:

试试1

//This still shows all animals from each farm, if there is at least one
//animal with the required DOB

var x = context.Farm.Where(y => y.StartDate >= myDate 
                           && y.Animal.Any(z => z.DOB >= otherDate)
                          ).Include("Animal");

试试2

//I subclassed the Farm class because i cant instantiate the class 
//from Entity Framework directly, and that should be my return type.
class Temp:Farm{}

var x = context.Farm.Where(y => y.StartDate >= myDate).Include("Animal")
        .Select(z => new Temp(){ 
                    owner = z.owner, 
                    animals = new TrackableCollection<Animal>(){ z.animals.Where(y => y.DOB >= newDate).SingleOrDefault() });

//Couple of things here:
//1: I instantiated a new TrackableCollection because thats what the collection
//type of Animal is inside Entity Framework.
//2: This still doesnt work for some reason, if i use this approach, the list 
//of animals in the farm comes with 0 elements.

试试3

阅读后:Ef-query-with-conditional-include

var x = (from farm in ctx.Farm
        from animal in farm.Animal
        where animal.DOB => newDate
        select new{farm, animal}).AsEnumerable().Select(x=> x.farm).Distinct().ToList();
//I have no idea how this works, but it does... 

有人愿意解释一下上面的工作原理吗?

基本上查询是选择父实体和通过所需参数过滤的子实体,并且实体框架通过“Relationship Fixup”知道选定的子实体与选定的父实体相关联,因此它们被添加到父集合中出色地。我认为这是一个 hacky 解决方案,但它确实有效。

--安德烈·D.

【问题讨论】:

  • 动物和农场之间需要建立关系。你有没有在你的例子中显示的?
  • 是的,我只是为了简单起见使用了这些类,但在我的实际模型中,这些类之间存在关系。实体模型是从 SQL Server 数据库导入的。
  • 我已经修改了我的回答来解释你的问题。

标签: c# linq entity-framework


【解决方案1】:

有人愿意解释一下上面的工作原理吗?

将以下内容视为两个单独的查询:

var x = (from farm in ctx.Farm
        from animal in farm.Animal
        where animal.DOB => newDate
        select new{farm, animal}).AsEnumerable().Select(x=> x.farm).Distinct().ToList();

爆发:

//Give me all farms
from farm in ctx.Farm

//Give me farms with animals with a DOB greater or equal to newDate
from animal in farm.Animal
where animal.DOB => newDate

//Select both so that neither are discluded from the query during execution
select new{farm, animal})

在执行时,查询将仅包含来自上述内容的数据,因此结果将包含每个Farm 中的两个,包括过滤后的Animals

Distinct 过滤重复项。

【讨论】:

  • 你确定 LazyLoadingEnabled 部分吗?因为我在我的模型中启用了它,但它只返回集合的一个子集,而不是你声明的整个集合(如果它打开的话)。
  • 我不确定,但在 EF 4 中,我不得不将其关闭。如果答案有所不同,我将继续删除这部分答案。
  • 我仍然不清楚在我进行选择后农场如何获得过滤后的动物,在我在问题的最后一部分提到的链接中,他们谈到了关系修复,但我似乎无法掌握概念
  • 我创建了一个测试项目来检查 LazyLoadingEnabled 部分,您是对的,如果启用它,则在子集合上选择所有项目。但由于某种原因,我仍然无法弄清楚,在我的真实项目中,LazyLoading 已启用,但它并没有返回所有元素,只返回过滤后的元素。
  • 他们都是db first,但实际项目使用自定义代码生成模板,我没有使用该模板测试过LazyLoading,我会告诉你:P
【解决方案2】:

你可以试试:

var result = context.Farms.Where(y => y.StartDate >= myDate)
                          .Select(z => new Farm { 
                            owner = z.owner, 
                            StartDate = z.StartDate,
                            animals = z.animals.Where(x => x.DOB >= newDate).ToList() 
                }).ToList();

【讨论】:

  • 问题是我正在使用实体框架生成的类,我不能直接实例化一个农场,这就是为什么在我第二次尝试中我将农场实体子类化并实例化它,但它仍然没有成功,我猜是因为与 TrackableCollection 类相关的东西......
  • 啊,好的,明白了,我不明白你问题中的那部分。如果您返回匿名类型,它会起作用吗?我想你可以把你的解决方案作为正确的答案。
  • 它适用于我的真实案例,但它不适用于这个虚构的案例 X-(我试图找出原因..
  • 另外,我不返回匿名类型,我返回的是Entity Framework类型,匿名类型只是作为一个桥梁。
【解决方案3】:

此时我通常会切换到服务器并创建一个可以从 EF 调用的函数。只是让这些实例更容易很多时间。

(对不起,我在没有测试 sql 的情况下输入这个。把它当作 Psudocode)

创建过程 GetFarmAnimals @StartDate 作为 [日期时间], @DOB 作为 [日期] 作为 Select * Farm left join Animals on(无论你的实际外键组合是什么) 其中 Farm.Startdate = @StartDate 和 Animal.DOB = @DOB 结束

然后只需将函数导入 EF。

【讨论】:

  • 是的,这是我最后的选择,但我更喜欢在 .Net 中而不是 T-SQL 中执行此操作,这也意味着对我的代码进行更多更改。
【解决方案4】:

你可以试试这个:

var filteredObjects = db.Farm.Where(x=>x.StartDate >= <startDateVariable> && x.Animal.Where(y=>y.DOB >= <DOBVariable>));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    • 2013-07-11
    • 1970-01-01
    相关资源
    最近更新 更多