在我通过Entity Framework实现先前的查询之前,不会执行下一个查询

时间:2017-12-27 15:48:07

标签: c# entity-framework linq

很抱歉,如果这是一个非常愚蠢的问题,但我无法理解为什么没有填充%html %head %title Photogram = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true = javascript_include_tag 'application', 'data-turbolinks-track' => true = csrf_meta_tags %body %nav.navbar.navbar-default .navbar-container .navbar-header %button.navbar-toggle.collapsed{"data-target" => "#bs-navbar-collapse-1", "data-toggle" => "collapse", type: "button"} %span.sr-only Toggle Navigation %span.icon-bar %span.icon-bar .navbar-brand= link_to "Photogram", root_path .collapse.navbar-collapse#bs-navbar-collapse-1 %ul.nav.navbar-nav.navbar-right %li = link_to "New Post", new_post_path %li = link_to "Login", '#' %li = link_to "Register", '#' .container = yield 属性。 :

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然后执行填充persons.ToList(),那么它就能完美运行。但是我在记忆中有一千个物体。

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.Cars中的条件person.Name != "Adam"填写db.Cars

是否可以在不在内存中实现(调用db.AnotherCars)数据的情况下重写此查询?

2 个答案:

答案 0 :(得分:1)

如果您没有运行tolist(),那么在您实际请求数据之前,由于LINQ查询中的延迟/延迟执行,您的查询将不会执行。在大多数情况下,您只有表达式树而不是实际对象。要切换到实际对象,您必须调用tolist()。实质上,您只是添加查询而不是实际请求数据。

答案 1 :(得分:1)

<强>被修改即可。我编辑了一个答案,因为它有错误。

阅读完所有评论后,我认为UNION ALL两个左连接可以解决这个问题:

  1. Persons(附加过滤器person.Name != "Adam")左连接表Cars
  2. Persons(附加过滤器person.Name == "Adam")左连接表AnotherCars
  3. 结果行将包含列:

    1. 是PersonID
    2. PersonName(我得到PersonName,如果你需要另一个,然后更改选择)
    3. CarID
    4. CarNumber。
    5. 以下是此查询的代码(我使用其他ORM。但我认为它应该适用于EF):

      // 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();
      

      如果您足以处理4个属性(PersonID, PersonName, CarID, CarNumber),则需要对其进行分类并在左连接中使用它(而不是select new {}使用select new YourNewDTO {})。

      如果你真的需要你的DTO,那么继续。

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

      imho,这是必要的信息:

      Ivan Stoev

        

      persons是一个查询。当你foreach它被执行时,那么你   对每个元素做一些事情,但因为你没有存储   结果,你基本上什么都不做。下次你枚举/收费   等人,查询将再次执行,并给你全新的   对象。 但是,如果您删除AsNoTracking,则可能会获得相同的结果   对象

           

      IQueryable<T>不是List<T>等存储空间   集合。即使IEnumerable<T>也不是。例如var q = Enumerable.Range(1, 10).Select(i => new SomeObject { Id = i });   将在您枚举时随时创建新对象

      问:所以这意味着foreach语句永远不会执行,直到我调用ToList()方法?

      通过 NetMage 回答:不,这意味着每个人对象仅存在于foreach内一次迭代。在foreach结束时他们都迷失了。