无法在EF中订购子对象

时间:2014-03-14 11:56:12

标签: c# linq entity-framework

我有一个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; }
}

2 个答案:

答案 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();