2017-10-17 34 views
4

,所以我必須在EF核心下面的查詢,這會導致重複的結果,即使艱難IM呼叫的第一或默認的就可以了實體框架的核心 - 遷移到.NET的核心後,首先返回重複結果

DateTime maxDate = SqlDateTime.MaxValue.Value; 
var results = (from r in _dbContext.audit_Results 
       join e in _dbContext.audit_DataEncounters on new { r.IdAudit, r.PatientFirstName, r.PatientLastName, r.PatientDOB } equals new { e.IdAudit, PatientFirstName = e.FirstName, PatientLastName = e.LastName, PatientDOB = e.DateOfBirth } into eJoin 
       let e = eJoin.Where(it => it.StartDate <= r.TransactionDate && r.TransactionDate <= (it.EndDate ?? maxDate)) 
          .OrderBy(it => it.Inpatient).OrderByDescending(it => it.StartDate) 
          .FirstOrDefault() 
       where r.IdAudit == idAudit && r.PatientFirstName == "ERIC" && r.PatientLastName == "BROOKS" 
       select new AuditResultBulkModel() 
       { 
        IdResult = r.IdResult, 
        map_HasPatient = eJoin.Any(), 
        map_IdEncounter = e != null ? e.IdEncounter : (int?)null 
       }).ToList(); 

產生的查詢看起來是這樣的:

SELECT * 
FROM [audit_Results] AS [r] 
LEFT JOIN [audit_DataEncounters] AS [e] ON ((([r].[IdAudit] = [e].[IdAudit]) AND (([r].[PatientFirstName] = [e].[FirstName]) OR ([r].[PatientFirstName] IS NULL AND [e].[FirstName] IS NULL))) AND (([r].[PatientLastName] = [e].[LastName]) OR ([r].[PatientLastName] IS NULL AND [e].[LastName] IS NULL))) AND (([r].[PatientDOB] = [e].[DateOfBirth]) OR ([r].[PatientDOB] IS NULL AND [e].[DateOfBirth] IS NULL)) 
WHERE (([r].[IdAudit] = @__idAudit_1) 
ORDER BY [r].[IdAudit], [r].[PatientFirstName], [r].[PatientLastName], [r].[PatientDOB] 

有人可以告訴我如何得到正確的結果嗎?

在過去的(實體框架.NET Framework中) - 這種用來生產使用OUTER APPLY非重複的結果。

編輯: 我的EF Core版本是2.0.0。

數據模型如下:

public class audit_Result 
{ 
    [Key] 
    public int IdResult { get; set; } 

    public int IdAudit { get; set; } 

    public bool? map_HasPatient { get; set; } 

    public int? map_IdEncounter { get; set; }   

    public virtual audit_Audit audit_Audit { get; set; } 
} 

public class audit_DataEncounter: IAuditEntity 
{ 
    [Key] 
    public int IdEncounter { get; set; } 

    public int IdAudit { get; set; } 

    [StringLength(50)] 
    public string FirstName { get; set; } 

    [StringLength(50)] 
    public string LastName { get; set; } 

    public DateTime? DateOfBirth { get; set; } 

    public DateTime? StartDate { get; set; } 

    public DateTime? EndDate { get; set; } 

    public bool? Inpatient { get; set; }   

    public virtual audit_Audit Audit { get; set; } 
} 


public class audit_Audit 
{ 
    [Key] 
    public int IdAudit { get; set; } 

    public virtual ICollection<audit_DataEncounter> audit_DataEncounters { get; set; } 

    public virtual ICollection<audit_Result> audit_Result { get; set; } 
} 
+0

如果你正在得到不需要的重複,你可以不使用不同的刪除它們嗎? 看看這篇文章:https://stackoverflow.com/questions/4539668/entity-framework-select-distinct-name – BastianBuhrkall

+0

請發佈在查詢中使用的實體模型。另外指定EF Core版本。 –

+0

@IvanStoev我將自己的數據模型 –

回答

5

不幸的是EF核心查詢轉換仍然是(如最新的在這個時候2.0)從最好的遠。如果您打開EF Core日誌記錄,您將看到許多警告,表明某些表達式無法翻譯,並將在本地進行評估(所謂的客戶端評估)。

唯一的解決方法我可以建議對於這類查詢是消除joinlet聲明和使用子查詢(重複的連接過濾器條件)map_HasPatientmap_IdEncounter投影性能:

var results = (
    from r in _dbContext.audit_Results 
    where r.IdAudit == idAudit && r.PatientFirstName == "ERIC" && r.PatientLastName == "BROOKS" 
    select new AuditResultBulkModel 
    { 
     IdResult = r.IdResult, 
     map_HasPatient = _dbContext.audit_DataEncounters 
     .Any(e => r.IdAudit == e.IdAudit && r.PatientFirstName == e.FirstName && r.PatientLastName == e.LastName && r.PatientDOB == e.DateOfBirth), 
     map_IdEncounter = _dbContext.audit_DataEncounters 
      .Where(e => r.IdAudit == e.IdAudit && r.PatientFirstName == e.FirstName && r.PatientLastName == e.LastName && r.PatientDOB == e.DateOfBirth 
       && e.StartDate <= r.TransactionDate && r.TransactionDate <= (e.EndDate ?? maxDate)) 
      .OrderBy(e => e.Inpatient).ThenByDescending(e => e.StartDate) 
      .Select(e => (int?)e.IdEncounter) 
      .FirstOrDefault() 

    }).ToList(); 

其轉換爲SQL像這樣的查詢:

SELECT [r].[IdResult], (
    SELECT CASE 
     WHEN EXISTS (
      SELECT 1 
      FROM [audit_DataEncounters] AS [e] 
      WHERE ((([r].[IdAudit] = [e].[IdAudit]) AND (([r].[PatientFirstName] = [e].[FirstName]) OR ([r].[PatientFirstName] IS NULL AND [e].[FirstName] IS NULL))) AND (([r].[PatientLastName] = [e].[LastName]) OR ([r].[PatientLastName] IS NULL AND [e].[LastName] IS NULL))) AND ([r].[PatientDOB] = [e].[DateOfBirth])) 
     THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) 
    END 
) AS [map_HasPatient], (
    SELECT TOP(1) [e0].[IdEncounter] 
    FROM [audit_DataEncounters] AS [e0] 
    WHERE ((((([r].[IdAudit] = [e0].[IdAudit]) AND (([r].[PatientFirstName] = [e0].[FirstName]) OR ([r].[PatientFirstName] IS NULL AND [e0].[FirstName] IS NULL))) AND (([r].[PatientLastName] = [e0].[LastName]) OR ([r].[PatientLastName] IS NULL AND [e0].[LastName] IS NULL))) AND ([r].[PatientDOB] = [e0].[DateOfBirth])) AND ([e0].[StartDate] <= [r].[TransactionDate])) AND ([r].[TransactionDate] <= COALESCE([e0].[EndDate], @__maxDate_1)) 
    ORDER BY [e0].[Inpatient], [e0].[StartDate] DESC 
) AS [map_IdEncounter] 
FROM [audit_Results] AS [r] 
WHERE (([r].[IdAudit] = @__idAudit_0) AND ([r].[PatientFirstName] = N'ERIC')) AND ([r].[PatientLastName] = N'BROOKS')