简体   繁体   English

EF6-使用可为空的属性(外键,TPH)时,SQL查询无效

[英]EF6 - invalid SQL query when using nullable property (foreign key, TPH)

Entity Framework generates invalid SQL query for the following LINQ query: 实体框架为以下LINQ查询生成无效的SQL查询:

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

My ParentId property is nullable int, foreign key to the same table (Id property). 我的ParentId属性是可以为null的int,指向同一表的外键(Id属性)。 My results is an empty array, but it shouldn't. 我的结果是一个空数组,但不应该。 I used similar query (checking that nullable property has no value) using other tables and it worked just fine. 我使用其他表使用类似的查询(检查可空属性是否没有值),并且工作正常。 In this case, the difference is that ParentId is foreign key and database table uses TPH. 在这种情况下,区别在于ParentId是外键,数据库表使用TPH。 Is this is a bug or I made some mistakes? 这是一个错误还是我犯了一些错误? Why EF ignores nullable property at all? 为什么EF完全忽略可为空的属性? My configuration and generated SQL by EF (naming is only for example, eg "Car"): 我的配置和通过EF生成的SQL(命名仅作为示例,例如“ Car”):

Context configuration: 上下文配置:

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

My class properties: 我的课程属性:

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

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

for: 对于:

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

I get empty result with generated SQL: 我生成的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

But it should be: 但是应该是:

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

for: 对于:

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

I get all entities (ParentId is ignored) with generated SQL: 我得到所有具有生成的SQL的实体(ParentId被忽略):

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)

Tested on EF6 6.0.2 / 6.1.1 and MS SQL Server. 在EF6 6.0.2 / 6.1.1和MS SQL Server上进行了测试。

Wow… that is a funny behavior, but the solution is pretty simple. 哇……这是一个有趣的行为,但是解决方案非常简单。 You have a nullable foreign key property but you defined the relationship as required. 您具有可为空的外键属性,但已根据需要定义了关系。 Just change 只是改变

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

to

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

And It will work. 而且它将起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM