linq嵌套选择新的

时间:2018-03-02 14:50:14

标签: c# sql asp.net linq linq-to-sql

我有2个数据库表,如Family和Cars,并有一个名为Families的类。他们用外键相互连接。

家庭

ID |姓氏|地址

汽车

ID | FamilyID |名称

一个家庭可以有多辆车。

我想将它绑定到网格,然后我写了这个查询:

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

网格填充数据。但是Cars列是空的。如何在第一个查询中执行此操作?或者,有一种简单的方法可以做到这一点吗?

3 个答案:

答案 0 :(得分:1)

试试这个:

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

答案 1 :(得分:0)

您的linq按设计返回IEnumerable<T> Lazy 。换句话说,当您执行第一个linq时,它不会立即获取数据。第一次使用时,实际上会获取数据。作为副作用,item.Cars += crItem.Name + ", ";被覆盖。可能的解决方法是添加.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();

<强>更新 您的代码正在var cr = Master.Conn ... item.ID);中对数据库进行多次调用,这是完全没必要的。相反,您可以使用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:请勿按照tbean的建议使用.Join(),因为.Join()会生成 INNER加入而不是 LEFT OUTER加入

答案 2 :(得分:0)

另一种方式:

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