2

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

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

class Animal{
    string Name;
    DateTime DOB;
}

问题:

我想选择开始日期 >= 2013/01/01及其动物的农场集合,但也按 DOB >= 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... 

有人愿意解释上述内容是如何工作的吗?

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

——安德烈·D。

4

4 回答 4

2

有人愿意解释上述内容是如何工作的吗?

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

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

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

Distinct过滤重复项。

于 2013-09-25T18:31:13.093 回答
0

你可以试试:

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();
于 2013-09-25T18:39:41.507 回答
0

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

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

创建过程 GetFarmAnimals @StartDate as [Datetime], @DOB as [Date] As Select * Farm left join Animals on(无论你的实际外键组合是什么)其中 Farm.Startdate = @StartDate 和 Animal.DOB = @DOB end

然后只需将函数导入 EF。

于 2013-09-25T18:52:00.620 回答
0

你可以试试这个:

var filteredObjects = db.Farm.Where(x=>x.StartDate >= <startDateVariable> && x.Animal.Where(y=>y.DOB >= <DOBVariable>));
于 2013-09-26T09:41:48.970 回答