2012-05-10 38 views
6

Tôi sử dụng EntityFramework 4 + POCO được tạo với tải Lười bị vô hiệu hóa.
Giả sử có các bảng SQL có tên là Bảng 1, Bảng 2, Bảng3Bảng4 và giả sử chúng chứa một số dữ liệu.
Giả sử POCO đại diện đơn giản của các bảng này trông như thế này:Truy vấn không trả lại gì khi có dữ liệu trong cơ sở dữ liệu

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; 
} 

Nếu mã sau đây sẽ được thực hiện:

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

EF sẽ tạo ra các câu lệnh SQL sau:

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' 

và truy vấn sẽ trả lại dữ liệu dự kiến.
Tuy nhiên, nếu đoạn mã sau sẽ được thực hiện:

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

EF sẽ tạo ra các câu lệnh SQL sau:

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' 

và truy vấn sẽ trở về không có gì.

Tại sao điều này có thể xảy ra?

EDIT

Sau đây là câu lệnh SQL để tạo các bảng trên:

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

Truy vấn này cũng sẽ trở lại không có hồ sơ và có thể đóng vai trò như một ví dụ tối thiểu :

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

SQL tạo:

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' 

Thêm vào đó, đây là một đoạn trích từ .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

Điều gì đó thuyết phục EF nó cần 'INNER' thay vì' LEFT' tham gia từ 'Bảng1' sang' Bảng2'. Bạn có thể cho chúng tôi biết thêm về lược đồ sql hay không, hoặc đến một ví dụ tối thiểu sai? – AakashM

+0

Vui lòng hiển thị bản đồ bạn đang sử dụng. –

+0

Tôi đã chỉnh sửa câu hỏi bằng câu lệnh SQL để tạo các bảng trên. Trong khi đó, tôi sẽ cố gắng để có được ví dụ tối thiểu mà đi sai. –

Trả lời

1

Dường như đã xảy ra sự cố với dữ liệu thực tế trong máy chủ SQL không nhất quán.
Như đã nêu there,

INNER JOIN hàng trở lại từ khóa khi có ít nhất một trận đấu ở cả hai bảng. Nếu có các hàng trong "Bảng 1" không có các kết quả phù hợp trong "Bảng 2", các hàng đó sẽ KHÔNG được liệt kê.

không có lý do nào cho truy vấn này thất bại, trừ khi không có hàng nào trong "Bảng 2" khớp với "Bảng 1".Điều này là kỳ lạ mặc dù, kể từ khi các ràng buộc FK được thực thi, nhưng điều đó xứng đáng với một câu hỏi khác và trường hợp này được đóng lại.

0

đoán của tôi là Include() s đang gây ra truy vấn của bạn để không đánh giá theo thứ tự bạn mong đợi, vì vậy TableDate không có sẵn khi Where() của bạn được gọi. Nếu bạn buộc đánh giá thì hãy gọi Where() của bạn ở đâu?

Các vấn đề liên quan