当前位置:  开发笔记 > 数据库 > 正文

从非平凡的IQueryable编译Linq到SQL查询

如何解决《从非平凡的IQueryable编译Linq到SQL查询》经验,为你挑选了0个好方法。

有没有办法使用CompiledQuery.Compile方法编译与IQueryable相关联的表达式?目前我有一个IQueryable,后面有一个非常大的表达式树.IQueryable是使用几种方法构建的,每种方法都提供组件.例如,两个方法可以返回IQueryables,然后在第三个方法中连接.出于这个原因,我无法在compile()方法调用中显式定义整个表达式.

我希望将表达式作为someIQueryable.Expression传递给compile方法,但是这个表达式不是编译方法所需的形式.如果我尝试通过将查询直接放入compile方法来解决这个问题,例如:

    var foo = CompiledQuery.Compile>(dc => dc.getUsers());
    var bar = foo(this);

我在datacontext中创建调用表单,我得到一个错误,说"getUsers未映射为存储过程或用户定义的函数".我再次不能将getUsers方法的内容复制到我进行编译调用的地方,因为它反过来使用其他方法.

有没有办法将从"getUsers"返回的IQueryable上的Expression传递给Compile方法?

更新 我试图使用以下代码强制我在系统上的意愿:

    var phony = Expression.Lambda>>(
        getUsers().Expression, Expression.Parameter(typeof(DataContext), "dc"));

    Func> wishful = CompiledQuery.Compile>(phony);
    var foo = wishful(this);

foo最终成为:

{System.Data.Linq.SqlClient.SqlProvider + OneTimeEnumerable`1 [Model.Entities.User]}

我没有选择在foo中查看结果,而不是提供扩展结果并运行查询我只看到消息"操作可能破坏运行时的稳定性".

我只需要找到一种方法让sql字符串只生成一次并用作后续请求的参数化命令,我可以在数据上下文中使用GetCommand方法手动完成,但是我必须显式设置所有参数并且自己进行对象映射,考虑到这个特定查询的复杂性,这是几百行代码.

更新

John Rusk提供了最有用的信息,所以我在这个上获得了胜利.然而,需要进行一些额外的调整,并且在此过程中我遇到了一些其他问题,所以我认为我会在答案上'展开'.首先,'操作可能会使运行时不稳定'错误不是由于表达式的编译,实际上是因为表达式树中有一些深入.在某些地方,我需要调用.Cast()方法来正式投射项目,即使它们的类型正确.在没有详细说明的情况下,当几个表达式组合成一个树并且每个分支可以返回不同的类型时,基本上需要这个,这些类型都是公共类的子类型.

解决了destabalizing问题后,我回到了编译问题.John的扩展解决方案几乎就在那里.它在树中查找方法调用表达式,并尝试将它们解析为方法通常返回的基础表达式.我对表达式的引用不是由方法调用提供的,而是由属性提供的.所以我需要修改执行扩展的表达式访问者以包含这些类型:

protected override Expression VisitMemberAccess(MemberExpression m) {
    if(m.Method.DeclaringType == typeof(ExpressionExtensions)) {
        return new ExpressionExpander().Visit((Expression)(((System.Reflection.PropertyInfo)m.Member).GetValue(null, null)));
    }
    return base.VisitMemberAccess(m);
}

这种方法可能并不适合所有情况,但它应该帮助任何发现自己陷入同样困境的人.

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有