我有一个linq查询,当对内存中的数据执行时有效但在使用EF时无法正常工作。
首先,这是我的查询(请注意,我已将查询更改为仅对单个值 justOneDcn
进行操作,而不是整个context.RepairDocuments
,以便生成的SQL读起来要干净得多):
var justOneDcn = context.RepairDocuments.Where(d => d.Dcn = "00001");
var q = from dcn in justOneDcn
let orderedHistory = dcn.History.OrderBy(h => h.Date)
let xdaHistoryPoint = orderedHistory.FirstOrDefault(h => h.Status == DocumentStatus.Xda)
select xdaHistoryPoint;
我删除了不必要的额外代码。问题是EF正在生成这个SQL:
SELECT
[... col list ...]
CASE WHEN ([Element1].[id] IS NOT NULL) THEN [Element1].[date] ELSE @p__linq__0 END AS [C2]
FROM (SELECT [Extent1].[id] AS [id]
FROM [dbo].[repair_document] AS [Extent1]
WHERE N'00001' = [Extent1].[dcn] ) AS [Filter1]
OUTER APPLY (SELECT TOP (1)
[... col list ...]
FROM [dbo].[repair_document_history] AS [Extent2]
WHERE ([Filter1].[id] = [Extent2].[repair_document_id]) AND (4 = CAST( [Extent2].[status] AS int)) AND ( CAST( [Extent2].[status] AS int) IS NOT NULL) ) AS [Element1]
-- p__linq__0: '1/1/0001 12:00:00 AM' (Type = DateTime2)
但是上面的SQL给出了错误的数据,它应该在where子句之后添加ORDER BY [Extent2].date
。以下修改后的SQL给出了正确的结果:
SELECT
[... col list ...]
CASE WHEN ([Element1].[id] IS NOT NULL) THEN [Element1].[date] ELSE @p__linq__0 END AS [C2]
FROM (SELECT [Extent1].[id] AS [id]
FROM [dbo].[repair_document] AS [Extent1]
WHERE N'00001' = [Extent1].[dcn] ) AS [Filter1]
OUTER APPLY (SELECT TOP (1)
[... col list ...]
FROM [dbo].[repair_document_history] AS [Extent2]
WHERE ([Filter1].[id] = [Extent2].[repair_document_id]) AND (4 = CAST( [Extent2].[status] AS int)) AND ( CAST( [Extent2].[status] AS int) IS NOT NULL)
ORDER BY [Extent2].date) AS [Element1]
-- p__linq__0: '1/1/0001 12:00:00 AM' (Type = DateTime2)
注意最后的ORDER BY
。
这让我抓狂!我究竟做错了什么?此外,将数据加载到内存不是一种选择,我有大约5000个Dcns,每个dcn在其历史表中有10-15条记录。
谢谢!
编辑:
这是实体声明
public class RepairDocument {
/* .... */
public virtual ICollection<RepairDocumentHistory> History { get; set; }
}
答案 0 :(得分:0)
如果您改为使用该怎么办:
var justOneDcn = context.RepairDocuments.Where(d => d.Dcn = "00001").OrderBy(d => d.History.Date);
从下面的命令中移除 {/ 1}}。
答案 1 :(得分:0)
你能做这样的事吗:
var item =
(from r in context.RepairDocuments
from h in r.History
where r.Dcn == "00001" && h.Status == DocumentStatus.Xda
orderby h.Date
select h).FirstOrDefault();