我想简化包含多个包含的linq查询。
我的模型很简单:网站链接到一个合同,链接到一个客户端。在那个客户端,我需要一个单一的请求电话,邮件和敬意(appelRef)。
我想要一个请求,因为请求背后是由实体框架转换为SQL Server请求。
这是linq请求:
var search =
from IMT.Site s in imtContext.IMTObjects.OfType<IMT.Site>()
.Include(
s => s.LienContratSiteRef
.Select(l => l.Contrat)
.Select(c => c.LienContratClientRef
.Select(l => l.Client)
.Select(cl => cl.Telephones ) ) )
.Include(s => s.LienContratSiteRef
.Select(l => l.Contrat)
.Select(c => c.LienContratClientRef
.Select(l => l.Client)
.Select(cl => cl.Mails ) ) )
.Include(s => s.LienContratSiteRef
.Select(l => l.Contrat)
.Select(c => c.LienContratClientRef
.Select(l => l.Client)
.Select(cl => cl.AppelRef ) ) )
where s.Reference.ToString() == siteId
select s;
你可以注意到阻止
.Include(
s => s.LienContratSiteRef
.Select(l => l.Contrat)
.Select(c => c.LienContratClientRef
.Select(l => l.Client)
..重复三次。是一种分解代码块的方法吗?
更新:有中间对象LienContratSiteRef和LienContratClientRef,关系为0 - *,因此LienContratSiteRef.Contrat和LienContratClientRef.Client都是集合。
我也尝试过:
.Include(
s => s.LienContratSiteRef
.Select(l => l.Contrat)
.Select(c => c.LienContratClientRef
.Select(l => l.Client)
.Select(cl => new { Tels = cl.Telephones, Mail = cl.Mails, Appel = cl.AppelRef} ) ) )
但它会导致运行时错误:
Include路径表达式必须引用导航属性 在类型上定义。
答案 0 :(得分:0)
基于字符串的链接
Include()
method supports a dot-delimited string parameter可以用来拉下完整的对象图,而不是进行多个链式选择调用:
.Include("LienContratSiteRif.Contrat.LienContratClientRef.Client")
从那里开始,如果你想要包含多个附加属性,我相信你可以为这些子属性添加另一个属性:
.Include("LienContratSiteRif.Contrat.LienContratClientRef.Client, Client.Telephones, ...")
基于Lambda的链接
您应该能够通过将基于lambda的包含链接到单个Include()
调用中来完成类似的操作:
.Include(c => LienContratSiteRif.Contrat.LienContratClientRef.Client)
答案 1 :(得分:0)
包含中的s => ...
可以重构为委托,然后仅.Include
委托多次。
看起来签名是Func<Site, IEnumerable<Client>>
?
E.g。
static IEnumerable<Client> Foo(Site site) => site.LienContratSiteRef
.Select(l => l.Contrat)
.Select(c => c.LienContratClientRef
.Select(l => l.Client)
答案 2 :(得分:0)
您似乎正在尝试进行实体框架投影!
项目允许您仅选择要返回的属性。 (就像SQL Select一样)
要使用投影,您的代码大致应如下所示:
var search = imtContext.IMTObjects.OfType<IMT.Site>()
.Where(s => s.Reference.ToString() == siteId)
.Select(s => new {
Telephones = s.LienContratSiteRef.Contrat.Select(c => c.LienContratClientRef.Client.Select(cli => cli.Telephones),
Mails = s.LienContratSiteRef.Contrat.Select(c => c.LienContratClientRef.Client.Select(cli => cli.Mails),
AppelRef = s.LienContratSiteRef.Contrat.Select(c => c.LienContratClientRef.Client.Select(cli => cli.AppelRef)
}).ToList();
如果Telephones
,Mails
,AppelRef
也是集合,那么您可以在运行查询后在内存中聚集这些集合:
var telephones = search.SelectMany(x => x.Telephones).ToList();
var mails = search.SelectMany(x => x.Mails).ToList();
var appelRefs = search.SelectMany(x => x.AppelRef).ToList();