我有以下通用可查詢(可能已經應用了選擇):
IQueryable<TEntity> queryable = DBSet<TEntity>.AsQueryable();
然後是Provider
類,如下所示:
public class Provider<TEntity>
{
public Expression<Func<TEntity, bool>> Condition { get; set; }
[...]
}
可以按以下方式為每個實例定義Condition
:
Condition = entity => entity.Id == 3;
現在我想選擇具有至少由DBSet
一個實體滿足的Condition
所有Provider
實例:
List<Provider> providers = [...];
var matchingProviders = providers.Where(provider => queryable.Any(provider.Condition))
問題是:我正在為列表中的每個Provider
實例啟動查詢。我寧願使用單個查詢來實現相同的結果。由於性能可疑,此主題尤其重要。如何使用單個查詢獲得相同的結果並使用Linq
語句或Expression Trees
提高性能?
有趣的挑戰。我看到的唯一方法是動態構建UNION ALL
查詢,如下所示:
SELECT TOP 1 0 FROM Table WHERE Condition[0]
UNION ALL
SELECT TOP 1 1 FROM Table WHERE Condition[1]
...
UNION ALL
SELECT TOP 1 N-1 FROM Table WHERE Condition[N-1]
然後使用返回的數字作為索引來獲取匹配的提供程序。
像這樣的東西:
var parameter = Expression.Parameter(typeof(TEntity), "e");
var indexQuery = providers
.Select((provider, index) => queryable
.Where(provider.Condition)
.Take(1)
.Select(Expression.Lambda<Func<TEntity, int>>(Expression.Constant(index), parameter)))
.Aggregate(Queryable.Concat);
var indexes = indexQuery.ToList();
var matchingProviders = indexes.Select(index => providers[index]);
請注意,通過替換上面的Select
with,我可以在不使用Expression
類的情況下構建查詢
.Select(_ => index)
但這會為每個索引引入不必要的SQL查詢參數。