简体   繁体   English

LINQ嵌套选择新

[英]linq nested select new

I've 2 db tables like as Family and Cars and have a class named Families. 我有2个db表,例如Family和Cars,并且有一个名为Families的类。 They connected eachother by a foreign key. 他们通过外键相互连接。

Family 家庭

ID | ID | Surname | 姓| Address 地址

Cars 汽车

ID | ID | FamilyID | 家庭ID | Name 名称

A family can have multiple cars. 一个家庭可以拥有多辆汽车。

I want to bind this to a grid and I wrote this query: 我想将此绑定到网格,并编写了此查询:

var data = from d in Master.Connection.Familys.Where(x => some conditions).OrderByDescending(d => d.ID)
                       select new Families
                       {
                           Id = d.ID,
                           Surname = d.Surname,
                           Address = d.Address,
                           Cars = ""
                       };

foreach (var item in data)
            {
                var cr = Master.Connection.Cars.Where(x => x.FamilyID == item.ID);
                if (!cr.Any()) continue;
                foreach (var crItem in cr)
                {
                    item.Cars += crItem.Name + ", ";
                }
            }

public class Families
{
    public int Id { get; set; }
    public string Surname { get; set; }
    public string Address { get; set; }
    public string Cars { get; set; }
}

Grid filled by data. 数据填充的网格。 However Cars column is empty. 但是,“汽车”列为空。 How can I do this in the first query? 如何在第一个查询中执行此操作? Or, is there a simple way to do this? 或者,有没有简单的方法可以做到这一点?

Try this: 尝试这个:

var data = from d in Master.Connection.Familys.Where(x => some conditions).OrderByDescending(d => d.ID)
                   select new Families
                   {
                       Id = d.ID,
                       Surname = d.Surname,
                       Address = d.Address,
                       Cars = ""
                   };


data.ForEach(f => f.Cars = String.Join(",", Master.Connection.Cars.Where(x => x.FamilyID == item.ID).Select(cr => cr.Name).ToArray()));

Your linq is returning IEnumerable<T> which is Lazy by design. 您的linq返回的IEnumerable<T>在设计上是惰性的。 In other words, when your first linq is executed, it doesn't fetch the data immediately. 换句话说,当您执行第一个linq时,它不会立即获取数据。 The data is actually fetched when it is used for the first time. 首次使用时实际上是获取数据。 As a side-effect, item.Cars += crItem.Name + ", "; 作为副作用, item.Cars += crItem.Name + ", "; is getting overwritten. 被覆盖。 A possible workaround is to add a .ToList() to fetch the data immediately. 一个可能的解决方法是添加一个.ToList()以立即获取数据。

var data = Master.Connection.Familys
    .Where(x => some conditions)
    .OrderByDescending(d => d.ID)
    .Select(d => new Families
                   {
                       Id = d.ID,
                       Surname = d.Surname,
                       Address = d.Address,
                       Cars = ""
                   })
    .ToList();

Update Your code is making multiple calls to the database in var cr = Master.Conn ... item.ID); 更新您的代码正在var cr = Master.Conn ... item.ID);多次调用数据库var cr = Master.Conn ... item.ID); which is totally unnecessary. 这完全没有必要。 Instead you can use GroupJoin as follows: 相反,您可以按以下方式使用GroupJoin

var data = Connection.Families   //main table
                .Where(x => some conditions)
                .GroupJoin(Connection.Cars   //left outer join
                    , f => f.ID   //join condition
                    , c => c.FamilyID // join condition
                    , (f, c) => new {Family = f, CarNames = c.Select(o => o.Name)})
                    .OrderByDescending(d => d.Family.ID)
                    .ToList()
                    .Select(o => new Families
                    {
                        Id = o.Family.ID,
                        Surname = o.Family.SurName,
                        Address = o.Family.Address,
                        // Check possible null from left join
                        Cars = o.CarNames.Count() > 0 ? o.CarNames.Aggregate((a, b) => a + "," + b) : string.Empty
                    })                    
                .ToList();

PS: Don't use .Join() as suggested by tbean because .Join() will produce INNER Join not a LEFT OUTER Join . PS:不要使用.Join()建议的.Join() ,因为.Join()会产生INNER Join而不是LEFT OUTER Join

Another way: 其他方式:

   private IQueryable<Family> GetFamilys()
    {
        return Master.Connection.Familys;
    }

    private IQueryable<Car> GetCars()
    {
         return Master.Connection.Cars;
    }

    public List<Families> FillFamilies()
    {
      var list = (from family in GetFamilys()
                   join car in GetCars() on family.ID equals car.familyID 
                   into groupJoin from subcar in groupJoin.DefaultIfEmpty()
                   select new Families
                  {
                   Id = family.ID,
                   Surname = family.Surname,
                   Address = family.Address,
                   Cars = subcar?.Name ?? String.Empty
                  }).ToList();
       return list;
     }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM