C# 直到我通过实体框架具体化上一个查询,下一个查询才会执行
抱歉,如果这是一个非常愚蠢的问题,但我无法理解为什么没有填充C# 直到我通过实体框架具体化上一个查询,下一个查询才会执行,c#,entity-framework,linq,C#,Entity Framework,Linq,抱歉,如果这是一个非常愚蠢的问题,但我无法理解为什么没有填充person.Cars属性: var persons = db.Persons.AsNoTracking() .Select(person => new PersonDto { ID = person.ID, Name = person.SP_Status.Name }); //The following code where person.Cars is not popul
person.Cars
属性:
var persons = db.Persons.AsNoTracking()
.Select(person => new PersonDto
{
ID = person.ID,
Name = person.SP_Status.Name
});
//The following code where person.Cars is not populated until I write persons.ToList()
foreach (var person in persons)
{
if (person.Name != "Adam")
{
person.Cars = (from ca in db.Cars
where ca.ID == person.ID
select new CarDTO
{
ID = ca.ID,
CarNumber = ca.DocNumber,
}).Distinct()
}
else
{
person.Cars = (from car in db.AnotherCars
where car.ID == person.ID
select new CarDTO
{
ID = car.ID,
CarNumber = car.DocNumber,
}).Distinct()
}
}
如果我通过persons.ToList()
将persons
具体化,然后执行填充person.Cars
,那么它可以完美地工作。但我记忆中有上千个物体
//this code works perfectly
persons.ToList();
foreach (var person in persons)
{
if (person.Name != "Adam")
{
person.Cars = (from ca in db.Cars
where ca.ID == person.ID
select new CarDTO
{
ID = ca.ID,
CarNumber = ca.DocNumber,
}).Distinct()
}
else
{
person.Cars = (from car in db.AnotherCars
where car.ID == person.ID
select new CarDTO
{
ID = car.ID,
CarNumber = car.DocNumber,
}).Distinct()
}
}
我错过了什么?请非常友好地解释,不要结束这个问题,它对我来说真的很重要。提前谢谢
我想做的是根据条件填写person.Name!=“Adam”
来自表db.Cars
或db.AnotherCars
是否可以重写此查询而不在内存中具体化(调用
.ToList()
)数据?如果不运行ToList(),由于LINQ查询中的延迟/延迟执行,在实际请求数据之前,将不会执行查询。在大多数情况下,您只有一个表达式树,而不是实际的对象。要切换到实际对象,必须调用tolist()。本质上,您只是添加到查询中,而不是实际请求数据。如果不运行tolist(),由于LINQ查询中的延迟/延迟执行,在实际请求数据之前,查询将不会执行。在大多数情况下,您只有一个表达式树,而不是实际的对象。要切换到实际对象,必须调用tolist()。本质上,您只是添加到查询中,而不是实际请求数据。已编辑。我编辑了一个答案,因为其中有错误
在阅读了所有评论之后,我决定通过UNION all
两个左连接来解决这个问题:
Persons
(带有附加过滤器person.Name!=“Adam”
)左连接表Cars
Persons
(带有附加过滤器person.Name==“Adam”
)左连接表其他车辆
李>
结果行将包含以下列:
persons
是一个查询。当您foreach
it时,它被执行,然后您
对每个元素执行一些操作,但由于您没有存储
结果,你基本上什么都不做。下次枚举/列出时
等人员,查询将再次执行并给您提供全新的
对象但是,如果删除AsNoTracking
,可能会得到相同的结果
对象
IQueryable
不是像List
等内存那样的存储
收藏。甚至IEnumerable
也不是。e、 g.var q=
Range(1,10)。选择(i=>newsomeobject{Id=i})代码>
将在枚举时创建新对象
问:这意味着在调用ToList()
方法之前,foreach
语句永远不会执行
NetMage回答:不,这意味着每个person对象只存在于foreach
中一次迭代。它们在foreach的末尾都丢失了。已编辑。我编辑了一个答案,因为其中有错误
在阅读了所有评论之后,我决定通过UNION all
两个左连接来解决这个问题:
表Persons
(带有附加过滤器person.Name!=“Adam”
)左连接表Cars
表Persons
(带有附加过滤器person.Name==“Adam”
)左连接表其他车辆
李>
结果行将包含以下列:
拟人
PersonName(我正在获取PersonName,如果您需要另一个,请更改选择)
龋齿
卡恩伯
以下是此查询的代码(我正在使用另一个ORM。但我想它应该在EF中工作):
imho,这是一个必要的信息:
伊万·斯托夫:
persons
是一个查询。当您foreach
it时,它被执行,然后您
对每个元素执行一些操作,但由于您没有存储
结果,你基本上什么都不做。下次枚举/列出时
等人员,查询将再次执行并给您提供全新的
对象但是,如果删除AsNoTracking
,可能会得到相同的结果
对象
IQueryable
不是像List
等内存那样的存储
收藏。甚至IEnumerable
也不是。e、 g.var q=
Range(1,10)。选择(i=>newsomeobject{Id=i})代码>
将在枚举时创建新对象
问:这意味着在调用ToList()
方法之前,foreach
语句永远不会执行
NetMage回答:不,这意味着每个person对象只存在于foreach
中一次迭代。他们在演讲结束时都迷路了。非常感谢你们对大家的澄清,伊万·斯托夫、网络法师、赫密德·阿巴索夫!非常感谢你们对所有人的澄清,伊万·斯托夫,尼特麦格,海米德·阿巴索夫!
// Getting persons.
var persons = db.Persons
.Where(p => p.ID <= 10) // any of your filtering condition on persons
.Select(p => new { p.ID, p.Name });
// Left join with 'Cars' table
var leftJoin1 = from p in persons.Where(p => p.Name != "Adam")
join c in db.Cars on p.ID equals c.PersonID into j
from c in j.Distinct().DefaultIfEmpty() // do you really need Distinc here?
select new
{
PersonID = p.ID,
PersonName = p.Name,
CarID = c.ID,
CarNumber = c.DocNumber
};
// Left join with 'AnotherCars' table
var leftJoin2 = from p in persons.Where(p => p.Name == "Adam")
join ac in db.AnotherCars on p.ID equals ac.PersonID into j
from ac in j.Distinct().DefaultIfEmpty() // do you really need Distinc here?
select new
{
PersonID = p.ID,
PersonName = p.Name,
CarID = ac.ID,
CarNumber = ac.DocNumber
};
// Resul query
var result = leftJoin1.Concat(leftJoin2)
.OrderBy(r => r.PersonID)
.ThenBy(r => r.CarID)
.ToList();
var personsWithCars = result.GroupBy(p => new { p.PersonID, p.PersonName })
.Select(g => new PersonDTO
{
ID = g.Key.PersonID,
Name = g.Key.PersonName,
Cars = result.Where(r => r.PersonID == g.Key.PersonID)
.Select(r => new CarDTO { ID = r.CarID, CarNumber = r.CarNumber })
.ToList()
});