2012-05-10 10 views
6

Io uso EntityFramework 4 + generato pocos con Lazy Loading disabilitato.
Diciamo che ci sono tabelle SQL denominate Tabella1, Tabella2, Tabella3 e Tabella4 e si presuppone che contengano alcuni dati.
Supponiamo che la rappresentazione POCO semplificata di queste tabelle si presenta così:Query rinviare nulla quando ci sono dati nel database

public class Table1 
{ 
    public int ID; 
    public DateTime TableDate; 
    public int Table2ID; 
    public Table2 Table2; 
    public ICollection<Table3> Table3s; 
} 

public class Table2 
{ 
    public int ID; 
    public string SomeString; 
    public int Table4ID; 
    public Table4 Table4; 
} 

public class Table3 
{ 
    public int ID; 
    public int Table1ID; 
    public Table1 Table1; 
    public decimal SomeDecimal; 
} 

public decimal Table4 
{ 
    public int ID; 
    public string SomeName; 
} 

Se sarebbe stato eseguito il seguente codice:

Database DB = new Database(); // object context 
var result = DB.Table1 
    .Where(x => x.TableDate >= DateTime.MinValue); 

EF genererebbe la seguente istruzione SQL:

exec sp_executesql N'SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[TableDate] AS [TableDate], 
[Extent1].[Table2ID] As [Table2ID] 
FROM [dbo].[Table1] AS [Extent1] 
WHERE ([Extent1].[TableDate] >= @p__linq__0)',N'@p__linq__0 datetime2(7)',@p__linq__0='0001-01-01 00:00:00' 

e la query restituirebbe i dati previsti.
Tuttavia, se il codice seguente sarebbe eseguita:

Database DB = new Database(); // object context 
var result = DB.Table1 
    .Include("Table2") 
    .Include("Table2.Table4") 
    .Include("Table3") 
    .Where(x => x.TableDate >= DateTime.MinValue); 

EF genererebbe la seguente istruzione SQL:

exec sp_executesql N'SELECT 
[Project1].[ID2] AS [ID], 
[Project1].[ID] AS [ID1], 
[Project1].[TableDate] AS [TableDate], 
[Project1].[ID1] AS [ID2], 
[Project1].[SomeString] AS [SomeString], 
[Project1].[Table4ID] AS [Table4ID], 
[Project1].[ID3] AS [ID3], 
[Project1].[SomeName] AS [SomeName], 
[Project1].[ID4] AS [ID4], 
[Project1].[SomeDecimal] AS [SomeDecimal], 
[Project1].[Table1ID] AS [Table1ID] 
FROM (SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[TableDate] AS [TableDate], 
[Extent2].[ID] AS [ID1], 
[Extent2].[SomeString] AS [SomeString], 
[Extent2].[Table4ID] AS [Table4ID], 
[Extent3].[ID] AS [ID2], 
[Extent4].[ID] AS [ID3], 
[Extent4].[SomeName] AS [SomeName], 
[Extent5].[ID] AS [ID4], 
[Extent5].[SomeDecimal] AS [SomeDecimal], 
[Extent5].[Table1ID] AS [Table1ID], 
CASE WHEN ([Extent5].[ID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] 
FROM  [dbo].[Table1] AS [Extent1] 
INNER JOIN [dbo].[Table2] AS [Extent2] ON [Extent1].[Table2ID] = [Extent2].[ID] 
LEFT OUTER JOIN [dbo].[Table2] AS [Extent3] ON [Extent1].[Table2ID] = [Extent3].[ID] 
LEFT OUTER JOIN [dbo].[Table4] AS [Extent4] ON [Extent3].[Table4ID] = [Extent4].[ID] 
LEFT OUTER JOIN [dbo].[Table3] AS [Extent5] ON [Extent1].[ID] = [Extent5].[Table1ID] 
WHERE ([Extent1].[TableDate] >= @p__linq__0) 
) AS [Project1] 
ORDER BY [Project1].[ID2] ASC, [Project1].[ID] ASC, [Project1].[ID1] ASC, [Project1].[ID3] ASC, [Project1].[C1] ASC',N'@p__linq__0 datetime2(7)',@p__linq__0='0001-01-01 00:00:00' 

e la query restituirebbe nulla.

Perché questo potrebbe accadere?

EDIT

seguito sono le istruzioni SQL per creare le tabelle di cui sopra:

CREATE TABLE [dbo].[Table1](
[ID] [int] IDENTITY(1,1) NOT NULL, 
[Table2ID] [int] NOT NULL, 
[TableDate] [date] NOT NULL, 
CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED 
(
[ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

ALTER TABLE [dbo].[Table1] WITH NOCHECK ADD CONSTRAINT [FK_Table1_Table2] FOREIGN KEY([Table2ID]) 
REFERENCES [dbo].[Table2] ([ID]) 

ALTER TABLE [dbo].[Table1] CHECK CONSTRAINT [FK_Table1_Table2] 

CREATE TABLE [dbo].[Table2](
[ID] [int] NOT NULL, 
[SomeString] [nvarchar](50) NOT NULL, 
[Table4ID] [int] NULL, 
CONSTRAINT [PK_Table2] PRIMARY KEY CLUSTERED 
(
[ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

ALTER TABLE [dbo].[Table2] WITH NOCHECK ADD CONSTRAINT [FK_Table2_Table4] FOREIGN KEY([Table4ID]) 
REFERENCES [dbo].[Table4] ([ID]) 
ON UPDATE CASCADE 

ALTER TABLE [dbo].[Table2] CHECK CONSTRAINT [FK_Table2_Table4] 

CREATE TABLE [dbo].[Table3](
[ID] [int] IDENTITY(1,1) NOT NULL, 
[SomeDecimal] [decimal](18, 4) NOT NULL, 
[Table1ID] [int] NOT NULL, 
CONSTRAINT [PK_Table3] PRIMARY KEY CLUSTERED 
(
[ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

ALTER TABLE [dbo].[Table3] WITH NOCHECK ADD CONSTRAINT [FK_Table3_Table1] FOREIGN KEY([Table1ID]) 
REFERENCES [dbo].[Table1] ([ID]) 
ON DELETE CASCADE 

ALTER TABLE [dbo].[Table3] CHECK CONSTRAINT [FK_Table3_Table1] 

CREATE TABLE [dbo].[Table4](
[ID] [int] NOT NULL, 
[SomeName] [nvarchar](50) NOT NULL, 
CONSTRAINT [PK_Table4] PRIMARY KEY CLUSTERED 
(
[ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

EDIT 2

Questa query anche restituire nessun record e può servire come un esempio minimo :

Database DB = new Database(); 
var result = DB.Table1 
    .Include("Table2") 
    .Where(x => x.TableDate >= DateTime.MinValue); 

SQL generato:

exec sp_executesql N'SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[Table2ID] AS [Table2ID], 
[Extent1].[TableDate] AS [TableDate], 
[Extent2].[ID] AS [ID1], 
[Extent2].[SomeString] AS [SomeString], 
[Extent2].[Table4ID] AS [Table4ID], 
FROM [dbo].[Table1] AS [Extent1] 
INNER JOIN [dbo].[Table2] AS [Extent2] ON [Extent1].[Table2ID] = [Extent2].[ID] 
WHERE ([Extent1].[TableDate] >= @p__linq__0)',N'@p__linq__0 datetime2(7)',@p__linq__0='0001-01-01 00:00:00' 

Inoltre, ecco un estratto dal edmx:

<EntityContainer> 
     <AssociationSet Name="FK_Table1_Table2" Association="MyModel.Store.FK_Table1_Table2"> 
     <End Role="Table2" EntitySet="Table2" /> 
     <End Role="Table1" EntitySet="Table1" /> 
     </AssociationSet> 
</EntityContainer> 

<!-- ... --> 

<EntityType Name="Table2"> 
    <Key> 
    <PropertyRef Name="ID" /> 
    </Key> 
    <Property Name="ID" Type="int" Nullable="false" /> 
    <Property Name="SomeString" Type="nvarchar" Nullable="false" MaxLength="50" /> 
    <Property Name="Table4ID" Type="int" /> 
</EntityType> 

<!-- ... --> 

<EntityType Name="Table1"> 
    <Key> 
    <PropertyRef Name="ID" /> 
    </Key> 
    <Property Name="ID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> 
    <Property Name="TableDate" Type="date" Nullable="false" /> 
    <Property Name="Table2ID" Type="int" Nullable="false" /> 
</EntityType> 

<!-- ... --> 

<Association Name="FK_Table1_Table2"> 
    <End Role="Table2" Type="MyModel.Store.Table2" Multiplicity="1" /> 
    <End Role="Table1" Type="MyModel.Store.Table1" Multiplicity="*" /> 
    <ReferentialConstraint> 
    <Principal Role="Table2"> 
     <PropertyRef Name="ID" /> 
    </Principal> 
    <Dependent Role="Table1"> 
     <PropertyRef Name="Table2ID" /> 
    </Dependent> 
    </ReferentialConstraint> 
</Association> 
+3

Qualcosa è convincente EF ha bisogno di un join "INNER" piuttosto che "SINISTRA" da "Table1" a "Table2". Puoi dirci di più sullo schema sql, o venire a un esempio minimo che va storto? – AakashM

+0

Mostra la mappatura che stai utilizzando. –

+0

Ho modificato la domanda con istruzioni SQL per creare le tabelle precedenti. Nel frattempo cercherò di arrivare all'esempio minimo che va storto. –

risposta

1

Sembra che il problema con i dati effettivi nel server SQL sia incoerente.
Come dichiarato there,

L'INNER JOIN filari di ritorno di parole chiave quando v'è almeno una partita in entrambe le tabelle. Se ci sono delle righe in "Table1" che non hanno corrispondenze in "Table2", quelle righe NON verranno elencate.

non c'è alcun motivo per cui questa query non va a buon fine, a meno che non ci sia realmente nessuna riga in "Table2" che corrisponda a "Table1".Ciò è strano, poiché i vincoli FK sono applicati, ma ciò merita un'altra domanda e questo caso è chiuso.

0

La mia ipotesi è che la include() s stanno causando la vostra richiesta di non valutare nell'ordine ti aspetteresti, quindi il TableDate non è disponibile quando viene chiamato il tuo Where(). Cosa succede se forzate la valutazione, quindi chiamate il vostro Where()?

Problemi correlati