簡體   English   中英

在EF Core中使用TPH時,將屬性稱為查詢中的子類型

[英]Referring to properties as substypes in queries when using TPH in EF 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 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; }
   }

基本上,我有一個與區域關聯的資產。 並且可以將不同類型的區域放入一個層次結構中。

現在,我想查詢直接與特定區域關聯或通過其父區域間接關聯的所有“資產”。 可以進行這樣的查詢嗎?

我覺得這樣的事情應該可行:

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

但事實並非如此。 有可能做這樣的事情嗎?

事實證明,我並沒有窮盡地嘗試結合“ is”運算符對它進行鑄造(使用cast / as)的所有可能性。

基本上,以下兩個示例引發一個異常,該異常指定該屬性為“未定義”(System.ArgumentException:未為類型“ Area”定義屬性“ Int64 ParentAreaId”)

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

下一個示例將引發NullReferenceException(大概是因為它實際上在將表達式轉換為sql查詢之后使用謂詞來應用其他過濾器)。 因此,如果區域的類型不正確,則該區域將為null,並引發NullReferenceException。 (這是我在原始問題中發布的示例)

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

但是,以下方法實際上有效,並且基本上是我在發布此問題之前未嘗試的唯一組合(使用兩個運算符:is / as):

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

基本上,這意味着您應該始終在對EF Core的linq查詢中使用“ is / as”運算符(對於SQL Server提供程序至少)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM