variables - 带有捕获变量的 Lambda

标签 variables c#-3.0 subsonic lambda

考虑以下代码行:

private void DoThis() {
    int i = 5;
    var repo = new ReportsRepository<RptCriteriaHint>();

    // This does NOT work
    var query1 = repo.Find(x => x.CriteriaTypeID == i).ToList<RptCriteriaHint>();      

    // This DOES work
    var query1 = repo.Find(x => x.CriteriaTypeID == 5).ToList<RptCriteriaHint>();    
}

因此,当我将实际数字硬连接到 lambda 函数时,它工作正常。当我在表达式中使用捕获的变量时,它会返回以下错误:

No mapping exists from object type ReportBuilder.Reporter+<>c__DisplayClass0 to a known managed provider native type.

为什么?我该如何解决?

最佳答案

从技术上讲,解决此问题的正确方法是让框架接受来自您的 lambda 的表达式树来评估 i引用;换句话说,它是某些特定框架的 LINQ 框架限制。它目前正在尝试做的是解释 i作为成员访问数据库中已知的某种类型(提供者)。由于 lambda 变量捕获的工作方式,i局部变量实际上是隐藏类的一个字段,提供者无法识别的具有有趣名称的字段。

所以,这是一个框架问题。

如果你真的必须通过,你可以手动构造表达式,如下所示:

ParameterExpression x = Expression.Parameter(typeof(RptCriteriaHint), "x");
var query = repo.Find(
    Expression.Lambda<Func<RptCriteriaHint,bool>>(
        Expression.Equal(
            Expression.MakeMemberAccess(
                x,
                typeof(RptCriteriaHint).GetProperty("CriteriaTypeID")),
            Expression.Constant(i)),
        x)).ToList();

...但这只是受虐狂。

您对此条目的评论促使我进一步解释。

Lambda 可转换为两种类型之一:具有正确签名的委托(delegate),或 Expression<TDelegate>的正确签名。 LINQ to external databases(与任何类型的内存中查询相反)使用第二种转换。

编译器将 lambda 表达式转换为表达式树,大致来说,通过:

  1. 语法树由编译器解析 - 所有代码都会发生这种情况。
  2. 语法树在考虑到变量捕获后被重写。捕获变量就像在普通委托(delegate)或 lambda 中一样 - 因此会创建显示类,并将捕获的局部变量移入其中(这与 C# 2.0 匿名委托(delegate)中的变量捕获行为相同)。
  3. 新的语法树被转换为对 Expression 的一系列调用类,以便在运行时创建忠实地表示已解析文本的对象树。

LINQ to external data sources 应该采用这个表达式树并解释它的语义内容,并将树内的符号表达式解释为引用特定于其上下文的事物(例如数据库中的列)或立即值转换。通常,System.Reflection 用于查找特定于框架的属性来指导此转换。

但是,看起来 SubSonic 没有正确处理无法找到特定领域对应关系的符号引用;它不是评估符号引用,而是平底船。因此,这是一个 SubSonic 问题。

关于variables - 带有捕获变量的 Lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/339366/

相关文章:

找不到 Bash 变量分配和命令

javascript - 在 JavaScript 加载之前定义变量

sql - MySQL @变量

ssl - Chromecast 上的 Html5 音频 - SSL

mysql - SubSonic 生成命名空间,但我的网站无法识别它。

matlab - 为什么 Matlab R2010 不能从 R2007 加载神经网络对象?

c#-3.0 - 如何使用 slimdx 创建媒体播放器

c# - XAML 中 UI 设计的优点

c# - 如何确定对象是 <type> 还是 <type> 的后代

大数据库上的 SubSonic 3.0.0.3 t4 模板生成耗尽连接