2017-10-17 7 views
4

i ont donc une requête suivante dans le noyau ef, qui se traduit par des résultats en double, même im difficile d'appeler d'abord ou par défaut sur elleEntity Framework de base - Tout d'abord le retour des résultats en double après la migration vers noyau .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(); 

Le produit la requête ressemble à ceci:

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] 

Quelqu'un peut-il me dire comment obtenir les bons résultats?

Dans le passé (Entity Framework dans .net Framework) - utilisé pour produire des résultats non dupliqués à l'aide de OUTER APPLY.

Editer: La version My EF Core est 2.0.0.

modèle de données est la suivante:

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

Si vous obtenez des doublons indésirables ne pourriez-vous pas simplement les supprimer en utilisant distinct? Jetez un oeil à cet article: https://stackoverflow.com/questions/4539668/entity-framework-select-distinct-name – BastianBuhrkall

+0

Veuillez afficher le modèle d'entité utilisé dans la requête. Spécifiez également la version EF Core. –

+0

@IvanStoev j'ai ajouté mon modèle de données –

Répondre

5

Malheureusement EF traduction de requête de base est toujours (au plus tard à ce moment-2.0) loin d'être le meilleur. Si vous activez la journalisation EF Core, vous verrez beaucoup d'avertissements que certaines expressions ne peuvent pas être traduites et seront évaluées localement (ce que l'on appelle l'évaluation du client).

La seule solution que je pourrais suggérer pour cette requête particulière est d'éliminer les join et let déclarations et utiliser les sous-requêtes (avec double condition de jointure du filtre) pour map_HasPatient et map_IdEncounter propriétés de projection:

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

ce qui correspond à SQL requête comme ceci:

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')