[英]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.