2014-06-25 36 views
2

實體框架生成以下LINQ查詢無效SQL查詢:EF6 - 使用可爲空值屬性時無效的SQL查詢(外鍵,TPH)

Car[] results = this.DbContext.Cars 
    .Where(x => !x.ParentId.HasValue) // also for x.ParentId == null 
    .ToArray(); 

我的ParentId屬性是可空INT,外鍵相同的表(Id屬性)。我的結果是一個空數組,但它不應該。我用類似的查詢(檢查可空屬性沒有值)使用其他表,它工作得很好。在這種情況下,區別在於ParentId是外鍵,數據庫表使用TPH。這是一個錯誤還是我犯了一些錯誤?爲什麼EF忽略可空屬性?我的配置和生成的SQL由EF(命名是隻例如,例如 「汽車」):

Context配置:

// TPH (Table per Hierarchy) 
modelBuilder.Entity<Car>() 
    .Map<CarA>(x => x.Requires("type").HasValue(1)) 
    .Map<CarB>(x => x.Requires("type").HasValue(2)) 
    .Map<CarC>(x => x.Requires("type").HasValue(3)) 
    .Map<CarD>(x => x.Requires("type").HasValue(4)); 

// parent child relationship 
modelBuilder.Entity<Car>() 
    .HasMany(x => x.Children) 
    .WithRequired() 
    .HasForeignKey(child => child.ParentId); 

我的類屬性:

[Column("parent_id")] 
public int? ParentId { get; set; } 

public virtual List<Car> Children { get; set; } 

爲:

Car[] results = this.DbContext.Cars 
    .Where(x => !x.ParentId.HasValue) 
    .ToArray(); 

我用生成的SQL得到空結果:

SELECT 
    CAST(NULL AS int) AS [C1], 
    CAST(NULL AS int) AS [C2], 
    ... 
    ... 
    ... 
    CAST(NULL AS decimal(18,2)) AS [C20], 
    CAST(NULL AS datetime2) AS [C21] 
    FROM (SELECT 1 AS X) AS [SingleRowTable1] 
    WHERE 1 = 0 

但它應該是:

... 
... 
WHERE [Extent1].[car] IS NULL 

爲:

var results = this.DbContext.Cars 
    .Where(x => x.ParentId.HasValue) 
    .ToArray(); 

我得到的所有實體(的ParentId被忽略)與生成的SQL:

SELECT 
    [Extent1].[type] AS [type], 
    [Extent1].[id] AS [id], 
    [Extent1].[parent_id] AS [parent_id], 
    [Extent1].[name] AS [name], 
    ... 
    ... 
    ... 
    FROM [dbo].[car] AS [Extent1] 
    WHERE [Extent1].[type] IN (1,2,3,4) 

測試在EF6 6.0.2/6.1.1和MS SQL Server。

回答

3

哇......這是一個有趣的行爲,但解決方案非常簡單。 您有一個可爲空的外鍵屬性,但您已根據需要定義了該關係。 只要改變

modelBuilder.Entity<Car>() 
    .HasMany(x => x.Children) 
    .WithRequired() 
    .HasForeignKey(child => child.ParentId); 

modelBuilder.Entity<Car>() 
    .HasMany(x => x.Children) 
    .WithOptional() 
    .HasForeignKey(child => child.ParentId); 

,它會工作。