2013-05-20 19 views
6

Abbiamo problemi su una singola sviluppatrice e su alcuni client. Query singola Linq Genera due diverse query SQL. Il problema è in effetti che la seconda query ha l'istruzione "OUTER APPLY" che firebird non supporta. Pensiamo che non si tratti di un problema di codice, ma di problemi ambientali, ma incollo il codice.Entity Framework Genera query diverse su workstation diverse

LINQ:

AIds = (from x in context.RISK_T_ASSESS_HIST 
    where (x.ID_RISKOBJECT.HasValue && x.F_CREATEDON >= Freq.StartDate && x.F_CREATEDON <= Freq.EndDate) 
    group x by x.ID_RISKOBJECT into gr 
    let lastCreated = gr.Max(p => p.F_CREATEDON) 
    select new 
    { 
     ObjId = gr.Key 
     , 
     LastStatus = gr.Where(p => p.F_CREATEDON == lastCreated && p.ID_RISKOBJECT == gr.Key).Select(p => p.F_STATUS).FirstOrDefault() 
    }).Where(x => x.LastStatus == 0 || x.LastStatus == 1).Select(x => x.ObjId.Value).ToArray(); 

SQL con OUTER APPLY

SELECT 
"G"."ID_RISKOBJECT" AS "ID_RISKOBJECT" 
FROM (SELECT 
    "C"."A1" AS "C1", 
    "C"."K1" AS "ID_RISKOBJECT" 
    FROM (SELECT 
     "E"."ID_RISKOBJECT" AS "K1", 
     MAX("E"."F_CREATEDON") AS "A1" 
     FROM "RISK_T_ASSESS_HIST" AS "E" 
     WHERE (("E"."ID_RISKOBJECT" IS NOT NULL) AND ("E"."F_CREATEDON" >=  @p__linq__0)) AND ("E"."F_CREATEDON" <= @p__linq__1)  
     GROUP BY "E"."ID_RISKOBJECT" 
    ) AS "C") AS "G" 
OUTER APPLY (SELECT FIRST (1) 
    "I"."F_STATUS" AS "F_STATUS" 
    FROM "RISK_T_ASSESS_HIST" AS "I" 
    WHERE (((("I"."ID_RISKOBJECT" IS NOT NULL) AND ("I"."F_CREATEDON" >=  @p__linq__0)) AND ("I"."F_CREATEDON" <= @p__linq__1)) AND (("G"."ID_RISKOBJECT" =   "I"."ID_RISKOBJECT") OR (("G"."ID_RISKOBJECT" IS NULL) AND ("I"."ID_RISKOBJECT" IS  NULL)))) AND (("I"."F_CREATEDON" = "G"."C1") AND ("I"."ID_RISKOBJECT" =  "G"."ID_RISKOBJECT"))) AS "J"  
WHERE (0 = "J"."F_STATUS") OR (1 = "J"."F_STATUS") 

di lavoro SQL

SELECT 
"B"."ID_RISKOBJECT" AS "ID_RISKOBJECT" 
FROM (SELECT 
     "C"."ID_RISKOBJECT" AS "ID_RISKOBJECT", 
     (SELECT FIRST (1) 
      "I"."F_STATUS" AS "F_STATUS" 
       FROM "RISK_T_ASSESS_HIST" AS "I" 
     WHERE (((("I"."ID_RISKOBJECT" IS NOT NULL) AND ("I"."F_CREATEDON" >= @p__linq__0)) AND ("I"."F_CREATEDON" <= @p__linq__1)) AND (("C"."ID_RISKOBJECT" = "I"."ID_RISKOBJECT") OR (("C"."ID_RISKOBJECT" IS NULL) AND ("I"."ID_RISKOBJECT" IS NULL)))) AND (("I"."F_CREATEDON" = "C"."C1") AND ("I"."ID_RISKOBJECT" = "C"."ID_RISKOBJECT"))) AS "C1" 
    FROM (SELECT 
     "D"."A1" AS "C1", 
     "D"."K1" AS "ID_RISKOBJECT" 
     FROM (SELECT 
       "F"."ID_RISKOBJECT" AS "K1", 
       MAX("F"."F_CREATEDON") AS "A1" 
       FROM "RISK_T_ASSESS_HIST" AS "F" 
       WHERE (("F"."ID_RISKOBJECT" IS NOT NULL) AND ("F"."F_CREATEDON" >= @p__linq__0)) AND ("F"."F_CREATEDON" <= @p__linq__1) 
       GROUP BY "F"."ID_RISKOBJECT" 
     ) AS "D" 
    ) AS "C"  
) AS "B" 
     WHERE (0 = "B"."C1") OR (1 = "B"."C1") 

query generata per MSSQL Engine (che supporta due motori DB nel nostro APP)

SELECT 
[Project1].[ID_RISKOBJECT] AS [ID_RISKOBJECT] 
FROM (SELECT 
    [GroupBy1].[A1] AS [C1], 
    [GroupBy1].[K1] AS [ID_RISKOBJECT] 
    FROM (SELECT 
     [Extent1].[ID_RISKOBJECT] AS [K1], 
     MAX([Extent1].[F_CREATEDON]) AS [A1] 
     FROM [dbo].[RISK_T_ASSESS_HIST] AS [Extent1] 
     WHERE ([Extent1].[ID_RISKOBJECT] IS NOT NULL) AND ([Extent1].[F_CREATEDON] >= @p__linq__0) AND ([Extent1].[F_CREATEDON] <= @p__linq__1) 
     GROUP BY [Extent1].[ID_RISKOBJECT] 
    ) AS [GroupBy1]) AS [Project1] 
OUTER APPLY (SELECT TOP (1) 
    [Extent2].[F_STATUS] AS [F_STATUS] 
    FROM [dbo].[RISK_T_ASSESS_HIST] AS [Extent2] 
    WHERE ([Extent2].[ID_RISKOBJECT] IS NOT NULL) AND ([Extent2].[F_CREATEDON] >=  @p__linq__0) AND ([Extent2].[F_CREATEDON] <= @p__linq__1) AND (([Project1].[ID_RISKOBJECT] = [Extent2].[ID_RISKOBJECT]) OR (([Project1].[ID_RISKOBJECT] IS NULL) AND ([Extent2]. [ID_RISKOBJECT] IS NULL))) AND ([Extent2].[F_CREATEDON] = [Project1].[C1]) AND ([Extent2].[ID_RISKOBJECT] = [Project1].[ID_RISKOBJECT])) AS [Limit1]  
WHERE [Limit1].[F_STATUS] IN (0,1)  
+0

Quale approccio stai usando per EF? Codice prima o database prima? Cioè erediti da DbContext e DbSet o hai i file xml di .edmx? –

+0

Database Prima, a causa di problemi legacy, abbiamo edmx. posso fornire loro se sono necessari. – Lightning3

+0

Supponiamo anche mssql, farò dei test e riferirò – Lightning3

risposta

1

Si sta sviluppando contro SQL Server?

Se si utilizza .edmx, l'attributo ProviderManifestToken (di solito nelle prime 10 righe dell'XML) indica il set supportato di funzionalità SQL. Questo è determinato dal database utilizzato quando hai creato o aggiornato il modello dal database. Per esempio. un problema comune è lavorare contro un database locale di SQL 2008, quindi passare a un database 2005 e scoprire che l'applicazione si blocca perché non supporta datetime2 in SQL 2005. La correzione in questo caso è di modificare il valore creato automaticamente da 2008 a 2005

Non ho familiarità con il lavoro contro firebird ma suggerisco di guardare in quest'area.

+0

abbiamo avuto questo problema :) come hai detto, in mssql lo abbiamo risolto, e attualmente: ProviderManifestToken = "2008" funziona bene. – Lightning3

+0

incollerò l'intera riga da firebird: Lightning3

+0

Su MSSQL tutto funziona bene, il problema è specifico per firebird :( – Lightning3

1

Il problema è tra Net Framework 4.5 e firebirdsql.data.firebirdclient.dll - Quando sb ha installato questa versione di framework - EntityFramework genera istruzioni di applicazione esterne per firebird.

Probabilmente Jiri Cincura (cincura.net) deve indagare :)

Problema risolto dal declassamento .net framework a 4,0 piena

Problemi correlati