[英]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.