我需要从数据库中提取有关支持服务单的一些信息。每张票与医学成像系统相关联,并且每个系统可以具有或不具有与其相关联的服务封面。如果是这样,可能会有多个服务封面条目,但只有一个我们感兴趣。
我知道这对Linq无效,但我真正想做的是以下......
var tickets = cxt.SupportTickets
.Select( t => new {
ID = t.ID,
Customer = t.Customer.Name,
var cover = t.System.CoverItems.FirstOrDefault(ci => // some query)
CoverLevel = cover?.Level.Name,
Expiry = cover?.Expiry.ToLongDateString()
});
有没有办法做到这一点?我知道我可以从封面上为我想要的每一点数据重复t.CoverItems.FirstOrDefault(...)
位,但除了会产生的绝对可怕的代码混乱之外,它将是非常低效的,因为它需要做同样的事情每张票的子查询多次。
我考虑将其全部分解为foreach
循环,但后来我无法看到如何创建tickets
集合。我无法创建一个空集合,然后添加对象,因为它们是匿名类型,我不想考虑如何指定泛型类型!
任何想法?
答案 0 :(得分:2)
您可以提高可读性:
var tickets = cxt.SupportTickets
.Select(t => new {
Ticket = t,
CoverItem = t.System.CoverItems.FirstOrDefault(ci => // some query)
})
.Select(x => new {
ID = x.Ticket.ID,
Customer = x.Ticket.Customer.Name,
CoverLevel = x.CoverItem?.Level.Name,
Expiry = x.CoverItem?.Expiry.ToLongDateString()
});
答案 1 :(得分:2)
您可以使用查询表示法来使用let
子句:
var query=from t in cxt.SupportTickets
let cover = t.System.CoverItems.FirstOrDefault(ci => some query)
select new {
ID = t.ID,
Customer = t.Customer.Name,
CoverLevel = cover?.Level.Name,
Expiry = cover?.Expiry//.ToLongDateString()
};
最后会像@TimSchmelter一样回答,但对于类似的事情你可以使用let
。另外,我几乎可以肯定EF中不支持ToLongDateString()
方法。
答案 2 :(得分:1)
我试过这个(如果你想单独开发一个子查询,因为SoC原理):
var innerQuery = cxt.SupportTickets
.Where(artist => artist.coverId == SomeParameter)
.Select(artist => new {
artistId = artist.artistId,
artistCompleteName = artist.artistName,
artistMasterPiece = artist.CoverName
});
var tickets = cxt.SupportTickets
.Where(
t => innerQuery.Contains(t.coverId)
)
.Select( t => new {
ID = t.ID,
Customer = t.Customer.Name,
var cover = t.System.CoverItems.FirstOrDefault()
CoverLevel = cover?.Level.Name,
Expiry = cover?.Expiry.ToLongDateString()
});