这是我在尝试这样做时想到的一个实际有效的答案。异常表示“只能从实现 IQueryable 接口的实例构造”,因此答案似乎很简单:返回可查询的内容。返回时是否可以.Count()
? Yes!
public partial class YourObjectContext
{
private static MethodInfo GetMethodInfo(Expression<Action> expression)
{
return ((MethodCallExpression)expression.Body).Method;
}
public IQueryable<TResult> CreateScalarQuery<TResult>(Expression<Func<TResult>> expression)
{
return QueryProvider.CreateQuery<TResult>(
Expression.Call(
method: GetMethodInfo(() => Queryable.Select<int, TResult>(null, (Expression<Func<int, TResult>>)null)),
arg0: Expression.Call(
method: GetMethodInfo(() => Queryable.AsQueryable<int>(null)),
arg0: Expression.NewArrayInit(typeof(int), Expression.Constant(1))),
arg1: Expression.Lambda(body: expression.Body, parameters: new[] { Expression.Parameter(typeof(int)) })));
}
}
使用方法:
var query = context.CreateScalarQuery(() => context.Entity.Count());
MessageBox.Show(((ObjectQuery)query).ToTraceString());
基本上,它的作用是将非 IQueryable 查询包装在子选择中。它将查询转换为
from dummy in new int[] { 1 }.AsQueryable()
select context.Entity.Count()
except 让上下文的 QueryProvider 处理查询。生成的 SQL 与您所期望的差不多:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Entity] AS [Extent1]
) AS [GroupBy1]