简化示例:我的表格为FirstName
,LastName
。我有兴趣检索所有那些完全称呼不再为N的人,按长度排序。为此,我有这样的代码:
var result = await Context.People
.Select(p => new PersonWithSalutation
{
FirstName = p.FirstName,
LastName = p.FirstName,
FullSalutation = p.FirstName + " " + p.LastName
})
.Where(p => p.FullSalutation.Length < maxLength)
.OrderBy(p => p.FullSalutation)
.Take(maxResults)
.ToListAsync();
查询如下所示:
SELECT TOP (10)
[Project1].[C1] AS [C1],
[Project1].[Name] AS [Name],
[Project1].[Id] AS [Id],
[Project1].[C2] AS [C2]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
1 AS [C1],
...calculated stuff... AS [C2]
FROM [dbo].[People] AS [Extent1]
WHERE ...exactly the same stuff... <= @p__linq__3
) AS [Project1]
ORDER BY [Project1].[C2] ASC
这样做可以为数据库生成一个查询。问题是计算的投影,因为它在结果查询中出现两次:一次在SELECT
中,然后在WHERE
子句中。这个例子是简化的,但在我的实际情况下,我正在进行繁重的数学运算,我宁愿只计算一次。如您所见,C2在order子句中重用。我想对WHERE
子句做同样的事情,我认为这将涉及另一个子查询。我怎么做到这一点?
答案 0 :(得分:1)
由于查询的构建过程非常难以预测,因此您可以通过查找所需的linq
来花费大量时间。这就是为什么,我提供另一种方法。将FullSalutation
媒体资源添加到POCO
课程中,当Computed
或FirstName
发生变化时,将通过数据库计算(LastName
)。在这种情况下,当非常必要时,将执行计算,无需重复,如您所愿。
public class POCO
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string FullSalutation { get; private set; }
}
然后添加新迁移:
public override void Up()
{
//AddColumn("dbo.People", "FullSalutation", x => x.String());
Sql("ALTER TABLE dbo.People ADD FullSalutation AS FirstName + ' ' + LastName");
}
public override void Down()
{
DropColumn("dbo.People", "FullSalutation");
}
最后,您的查询将如下所示:
var result = await Context.People
.Where(p => p.FullSalutation.Length < maxLength)
.Select(p => new PersonWithSalutation
{
FirstName = p.FirstName,
LastName = p.LastName,
FullSalutation = p.FullSalutation
}).OrderBy(p => p.FullSalutation).Take(maxResults).ToListAsync();