C# 在EF Core中使用TPH时,在查询中将属性引用为子类型

C# 在EF Core中使用TPH时,在查询中将属性引用为子类型,c#,entity-framework-core,C#,Entity Framework Core,我有以下课程: public abstract class Area { public long Id { get; set; } [Required] public string Name { get; set; } public ICollection<Asset> Assets { get; set; } } public class AreaWithParent : Area {

我有以下课程:

   public abstract class Area
   {
      public long Id { get; set; }

      [Required]
      public string Name { get; set; }

      public ICollection<Asset> Assets { get; set; }
   }

   public class AreaWithParent : Area
   {
      public AreaAsParent ParentArea { get; set; }

      public long ParentAreaId { get; set; }
   }

   public class AreaAsParent : Area
   {
      public ICollection<AreaWithParent> AreasWithParent { get; set; }
   }

   public class Asset
   {
      public long Id { get; set; }

      public long? AreaId { get; set; }

      public Area Area { get; set; }
   }

但事实并非如此。有可能这样做吗?

事实证明,我并没有用尽全力尝试将它与“Is”操作符结合使用(使用cast/As)

基本上,以下两个示例引发一个异常,指定属性为“未定义”(System.ArgumentException:未为类型“Area”定义属性“Int64 ParentAreaId”)

下一个示例抛出一个NullReferenceException(可能是因为它在将表达式转换为sql查询后实际使用谓词应用额外的过滤器)。因此,如果该区域的类型不正确,它将为null,因此引发NullReferenceException。(这是我在原始问题中发布的示例)

然而,以下方法确实有效,并且基本上是我在发布此问题之前没有尝试过的唯一组合(使用两个操作符:is/as):


基本上,这意味着您应该在对EF Core的linq查询中始终使用“is/as”操作符(至少对于SQL Server提供程序而言)。

事实证明,我并没有用尽一切可能将它(使用cast/as)与“is”操作符结合使用

基本上,以下两个示例引发一个异常,指定属性为“未定义”(System.ArgumentException:未为类型“Area”定义属性“Int64 ParentAreaId”)

下一个示例抛出一个NullReferenceException(可能是因为它在将表达式转换为sql查询后实际使用谓词应用额外的过滤器)。因此,如果该区域的类型不正确,它将为null,因此引发NullReferenceException。(这是我在原始问题中发布的示例)

然而,以下方法确实有效,并且基本上是我在发布此问题之前没有尝试过的唯一组合(使用两个操作符:is/as):


基本上,这意味着您应该在对EF Core的linq查询中始终使用“is/as”运算符(至少对于SQL Server提供程序而言)。

尝试运行查询时会发生什么情况?谢谢您的评论。我进一步调查了这个问题。请参阅下面我的答案。当您尝试运行查询时会发生什么情况?谢谢您的评论。我进一步调查了这个问题。见下面我的答案。
    var areaId = /* the area id I want to query for */

    var assets = await ctx.Assets
       .Where( x => x.AreaId == areaId || ( x.Area as AreaWithParent ).ParentAreaId == areaId )
       .ToListAsync( cancellationToken );
var areaId = /* the area id I want to query for */

var assets = await ctx.Assets
   .Where( x => x.AreaId == areaId || ( (AreaWithParent)x.Area ).ParentAreaId == areaId )
   .ToListAsync( cancellationToken );
var areaId = /* the area id I want to query for */

var assets = await ctx.Assets
   .Where( x => x.AreaId == areaId || ( x.Area is AreaWithParent && ( (AreaWithParent)x.Area ).ParentAreaId == areaId ) )
   .ToListAsync( cancellationToken );
var areaId = /* the area id I want to query for */

var assets = await ctx.Assets
   .Where( x => x.AreaId == areaId || ( x.Area as AreaWithParent ).ParentAreaId == areaId )
   .ToListAsync( cancellationToken );
var areaId = /* the area id I want to query for */

var assets = await ctx.Assets
   .Where( x => x.AreaId == areaId || ( x.Area is AreaWithParent && ( x.Area as AreaWithParent ).ParentAreaId == areaId ) )
   .ToListAsync( cancellationToken );