簡體   English   中英

在 WebApi 中過濾 EF-Core 和 TPT 繼承中的某些子類型

[英]Filtering for certain sub-types in EF-Core and TPT-inheritance in WebApi

我正在使用 EF-Core 並有一個類似的數據模型(只是一個動物的例子,以保持簡單)。 繼承通過 TPT(每種類型的表)映射到數據庫中。

public abstract class Animal { }

public class Monkey : Animal { }

public class Bear : Animal { }

public class Dog: Animal { }

在我的前端,我展示了所有的動物。 所以我創建了一個基本類型(抽象)的查詢並在前端顯示所有動物。 但現在我想通過查詢字符串添加一個過濾器,只顯示某種類型的動物(例如狗和猴子)。

這樣做的最佳做法是什么?

不幸的是,對於 TPT,我沒有鑒別器來過濾? 這是怎么做到的?

目前,我正在通過字符串數組在我的 WebApi-Conroller 中接收選定的類型,例如:

public IActionResult(string[] types) {
    // ...
}

一個想法是將這個字符串數組映射到 Type,然后使用 .OfType。 但是我遇到了無法鏈接 OfType 的問題,因為鏈接時結果集始終為零。

直接在數據庫上進行過濾是完美的,所以出於性能原因,我想避免在內存中進行過濾。

有任何想法嗎?

實際上你不需要訪問鑒別器。 所有繼承模型(添加時的 TPH、TPT 和 TPC)都使用基於類型的查詢條件來過濾基本集。 OfType只是其中之一,通常 C# 運算符is T用於過濾, as T或 cast (T)用於訪問。

應用基於Type的過濾器沒有開箱即用的方法,但可以使用Expression類創建它 - C# 的對應方法is TExpression.TypeIs ,它與Expression.OrElse結合允許您動態構建所需的謂詞.

例如:

public static Expression<Func<T, bool>> MakeFilter<T>(this IEnumerable<Type> types)
{
    var parameter = Expression.Parameter(typeof(T), "e");
    var body = types.Select(type => Expression.TypeIs(parameter, type))
        .Aggregate<Expression>(Expression.OrElse);
    return Expression.Lambda<Func<T, bool>>(body, parameter);
}

和頂級查詢助手:

public static IQueryable<T> OfTypes<T>(this IQueryable<T> source, IEnumerable<Type> types)
    => source.Where(types.MakeFilter<T>());

將其應用於您的樣本:

var types = new[] { typeof(Dog), typeof(Monkey) };
var query = db.Set<Animal>().OfTypes(types);

生成以下調試視圖表達式

DbSet<Animal>()
    .Where(e => (e is Dog) || (e is Monkey))

並查詢 SqlServer 提供程序:

SELECT [a].[Id], [a].[Name], CASE
    WHEN [m].[Id] IS NOT NULL THEN N'Monkey'
    WHEN [d].[Id] IS NOT NULL THEN N'Dog'
    WHEN [b].[Id] IS NOT NULL THEN N'Bear'
END AS [Discriminator]
FROM [Animals] AS [a]
LEFT JOIN [Bears] AS [b] ON [a].[Id] = [b].[Id]
LEFT JOIN [Dogs] AS [d] ON [a].[Id] = [d].[Id]
LEFT JOIN [Monkeys] AS [m] ON [a].[Id] = [m].[Id]
WHERE ([d].[Id] IS NOT NULL) OR ([m].[Id] IS NOT NULL)

它並不完美(EF Core 團隊有優化的空間——TPH 做到了這一點,添加了一種告訴鑒別器“完整”的方法,但 TPT 仍然缺乏這種能力),但是過濾數據庫方面是需要的。

暫無
暫無

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

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