【发布时间】:2020-03-27 07:04:02
【问题描述】:
我正在尝试使用 Entity Framework Core 来生成一个高性能的服务器端 SQL 查询,它计算几组中的记录。例如,假设我有一张桌子:
CREATE TABLE ExOrders
(
Id UNIQUEIDENTIFIER,
Column1 VARCHAR(250),
Column2 INT,
ColumnN VARCHAR(500),
)
结果应该是选择查询:
select
count(<count1Condition>) as C1,
count(<count2Condition>) as C2
from
ExOrders
where
<whereGenericCondition>
对于每个条件,我已经生成了一个 Expression<Func<T, bool>> 表达式。
到目前为止我尝试了什么
-
Linq
Count()函数我试图通过如下查询获得上述结果:
Expression<Func<T, bool>> whereGenericCondition = GetExpression1();
Expression<Func<T, bool>> count1Condition = GetExpression2();
Expression<Func<T, bool>> count2Condition = GetExpression3();
var countRequestS1 = _dbcontext.Set<T>()
.Where(whereGenericCondition)
.GroupBy(s => 0)
.Select(agg => new
{
C1 = agg.Count(count1Condition), // <- parameter error
C2 = agg.Count(count2Condition) // <- parameter error
});
问题是Count 扩展不支持表达式参数。
错误:
参数 2:无法从 'System.Linq.Expressions.Expression
>' 转换为 'System.Func '
-
带有
AsQueryable()的LinqCount()函数我尝试在
Count方法之前调用AsQueryable:
var countRequestS2 = _dbcontext.Set<T>()
.Where(whereGenericCondition)
.GroupBy(s => 0) // <- from this point onward it is executed clientside
.Select(agg => new
{
C1 = agg.AsQueryable().Count(count1Condition),
C2 = agg.AsQueryable().Count(count2Condition)
});
但在这种情况下,它只是将所有数据放入应用程序,并在本地处理(在我的情况下是不可接受的情况,因为有数十万行)。
- 预编译表达式
我还尝试在使用 count1Condition 和 count2Condition 表达式之前编译它们:
var countRequestS3 = _dbcontext.Set<T>()
.Where(whereGenericCondition)
.GroupBy(s => 0) // <- from this point onward it is executed clientside
.Select(agg => new
{
C1 = agg.Count(x => count1Condition.Compile()(x)),
C2 = agg.Count(x => count2Condition.Compile()(x))
});
但在这种情况下,它只是将所有数据获取到应用程序中,与 #2 相同。
- 实现我自己的
Count()
我最后一次尝试是实现我自己的CountAfterGroupByMethod,但我得到了一个与泛型 T 类型函数相关的错误。
在上下文模型构建器中,这会崩溃:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDbFunction(typeof(CountAfterGroupByExtensions).GetMethod("CountAfterGroupBy"), options =>
{
options.HasTranslation(CountAfterGroupByExpressionTranslator.Translate);
});
// where CountAfterGroupBy is
// public static int CountAfterGroupBy<TSource>(this IEnumerable<TSource> source, Expression<Func<TSource, bool>> predicate)
}
有错误:
System.ArgumentException: 'DbFunction 'CountAfterGroupByExtensions.CountAfterGroupBy' 是通用的。不支持泛型方法。'
#3 或#4 中是否有我看不到的缺陷?或者还有什么我可以尝试的吗?
【问题讨论】:
-
你希望它在这里返回的sql是什么?通常在 sql 中,如果您计算两列(这似乎是您正在做的),除非您尝试执行某种 case 语句,否则您将获得两次相同的结果。这是另一个类似的问题:stackoverflow.com/questions/39590025/…
-
我很确定 LINQ 翻译不支持您尝试执行的操作。您可能需要运行两个单独的查询并在 EF 核心 GitHub 页面上提交功能提案。
-
确切的 EF Core 版本是什么(不幸的是,这很重要)?
标签: c# sql-server linq entity-framework-core expression