LINQ到实体查询
问题描述:
考虑以下查询:LINQ到实体查询
var profilelst =
(
from i in dbContext.ProspectProfiles
where i.CreateId == currentUser
select new ProspectProfile
{
ProspectId = i.ProspectId,
Live = i.Live,
Name = i.Name,
ServiceETA = i.Opportunities.OrderByDescending(t => t.FollowUpDate)
.FirstOrDefault()
.ServiceETA.ToString(),
FollowUpDate = i.Opportunities.OrderByDescending(t => t.FollowUpDate)
.FirstOrDefault()
.FollowUpDate
}
)
.ToList();
return profilelst.OrderByDescending(c=>c.FollowUpDate)
.Skip(0).Take(endIndex)
.ToList();
在这里,在此查询,请看看FollowUpDate
和ServiceType
,这些都我有机会表取回,有没有其他的解决办法得到这些既..
一对多的关系在表像:ProspectProfile -> Opportunities
无论我写的查询是好的或有任何其他解决办法,可以在更简单的方式来完成。
答
可以提高的唯一的事情是避免通过改变你的代码,这个订货两次:
var profilelst
= dbContext.ProspectProfiles
.Where(i => i.CreateId == currentUser)
.Select(i =>
{
var opportunity
= i.Opportunities
.OrderByDescending(t => t.FollowUpDate)
.First();
return new ProspectProfile
{
ProspectId = i.ProspectId,
Live = i.Live,
Name = i.Name,
ServiceETA = opportunity.ServiceETA.ToString(),
FollowUpDate = opportunity.FollowUpDate
}
}).ToList();
return profilelst.OrderByDescending(c => c.FollowUpDate).Take(endIndex).ToList();
我做了一些改动,以您的原始查询:
- 我改成了使用方法链式语法。在我看来,阅读起来要容易得多。
- 我删除了不必要的
Skip(0)
。 - 最大的变化是在
Select
部分:- 我改变
FirstOrDefault
到First
,因为你无论如何访问返回值的属性。如果没有机会,这会引发一个描述性例外。这比你有更好的:在你的情况下,它会抛出一个NullReferenceException
。这很糟糕,NullReferenceExceptions
总是表明你的程序存在一个错误,而且根本没有描述。 - 我将选择机会的部分移出了初始化程序,因此我们只需要执行一次而不是两次。
- 我改变
答
有在查询了不少问题:
-
不能投射到一个实体(
您的实体数据模型(select new ProspectProfile
)。 LINQ到实体仅支持突起到匿名类型(select new
)或其它类型的其不是用于数字或DateTime
类型在LINQ不支持将实体(ServiceETA.ToString()
)select new MySpecialType
) ToString()
的一部分如果Opportunities
集合为空,并且ServiceETA
是非空值类型(如DateTime
),因为EF不能兑现任何值到这样的可变FirstOrDefault().ServiceETA
(或FollowUpdate
)将抛出异常。在第一次查询后将使用
.ToList()
执行数据库中的查询并加载完整的结果。您的后续Take
发生在完整列表的内存中,而不是在数据库中。 (你有效地将整个结果列表从数据库加载到内存中,然后丢弃除Take
en之外的所有对象。
要解决四个问题,你可以尝试以下方法:
var profilelst = dbContext.ProspectProfiles
.Where(p => p.CreateId == currentUser)
.Select(p => new
{
ProspectId = p.ProspectId,
Live = p.Live,
Name = p.Name,
LastOpportunity = p.Opportunities
.OrderByDescending(o => o.FollowUpDate)
.Select(o => new
{
ServiceETA = o.ServiceETA,
FollowUpDate = o.FollowUpDate
})
.FirstOrDefault()
})
.OrderByDescending(x => x.LastOpportunity.FollowUpDate)
.Skip(startIndex) // can be removed if startIndex is 0
.Take(endIndex)
.ToList();
这会给你一个匿名对象的列表。如果您在实体ProspectProfile
的列表中需要结果,则必须复制此查询后的值。请注意,如果ProspectProfile
没有Opportunities
,LastOpportunity
的结果可能为null
。
重新格式化的代码使其可读,但是,实际问题并不清楚。 –
您是否测试过您的第一个查询是否可用?我怀疑。 – Slauma