c# - 如何为 IQueryable.Count 获取 ToTraceString

标签 c# linq lambda linq-to-entities expression-trees

我使用 ((ObjectQuery)IQueryable).ToTraceString() 获取和调整将由 LINQ 执行的 SQL 代码。

我的问题是,与大多数 IQueryable 方法不同,IQueryable.Count 定义如下:

    public static int Count(this IQueryable source) {
        return (int)source.Provider.Execute(
            Expression.Call(
                typeof(Queryable), "Count",
                new Type[] { source.ElementType }, source.Expression));
    }

执行查询而不编译并返回 IQueryable。 我想通过这样的方式来解决这个问题:

public static IQueryable CountCompile(this IQueryable source) {
    return source.Provider.CreateQuery(
        Expression.Call(
            typeof(Queryable), "Count",
            new Type[] { source.ElementType }, source.Expression));
}

但是 CreateQuery 给了我以下异常:

LINQ to Entities 查询表达式只能从实现 IQueryable 接口(interface)的实例构造。

最佳答案

这是我在尝试这样做时得出的实际可行答案。异常说“只能从实现 IQueryable 接口(interface)的实例构造”,所以答案似乎很简单:返回一个可查询的东西。返回 .Count() 时可能吗?是的!

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]

关于c# - 如何为 IQueryable.Count 获取 ToTraceString,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8302656/

相关文章:

c# - 如何将 Luis 集成到机器人构建器中

c# - 如何在没有 View 模型的情况下使用@Html.EditorFor()

c# - LINQ 中具有外连接的 Nullable Int

Java lambda 方法和新对象

javascript - javascript/jquery 中的 lambda 包装器——为什么?

c# - 如何在.Net 中进行实时音高检测?

c# - 使用 LINQ 或 C# 清理字符串中特定 HTML 的算法

c# - 使用经度和纬度查找最近的位置

c++ - 在 C++ 中将函数作为参数执行

c# - 创建 View 时出错,通过反射调用的方法抛出未捕获的异常