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”
    )左连接表
    其他车辆
    结果行将包含以下列:

  • 拟人
  • 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
    中一次迭代。它们在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()
                                             });