C# 如何使匿名方法在LINQ to实体中运行?

C# 如何使匿名方法在LINQ to实体中运行?,c#,.net,entity-framework,entity-framework-4.1,expression,C#,.net,Entity Framework,Entity Framework 4.1,Expression,我试图构建一个通用方法,EF4.1可以在数据库和本地内存中查找表中与特定条件匹配的特定行 到目前为止,这就是我所拥有的 我是来电者 dbEntities.MyTables.LocalAndDb(delegate(MyTable s) { return s.Description.Contains("test"); }); 这是LocalAndDb public static object LocalAndDb<T>(this DbSet<T&g

我试图构建一个通用方法,EF4.1可以在数据库和本地内存中查找表中与特定条件匹配的特定行

到目前为止,这就是我所拥有的

我是来电者

dbEntities.MyTables.LocalAndDb(delegate(MyTable s)
                { return s.Description.Contains("test"); });
这是LocalAndDb

public static object LocalAndDb<T>(this DbSet<T> myTable, Func<T, bool> function) where T : class
{   
    // look in local 
    var item = myTable.Local.Where(o => function((T)o)).FirstOrDefault()
    // if not exist, look in the database
    if (item == null)
    {
        Expression<Func<T, bool>> predicate = (u) => function(u);
        item = myTable.Where(predicate).FirstOrDefault();
    }
    return item;
}
当它调用数据库时,会抛出此错误

“LINQ to实体中不支持LINQ表达式节点类型‘Invoke’。”

我想这是因为我传入了一个匿名方法,而它不知道如何将其转换为SQL。我原以为将它转换为表达式对象就可以了,但它对我仍然不起作用


要使匿名方法成为LINQ可以转换为SQL的方法,我需要做些什么?

要实现这一点,需要将lambda表达式作为表达式树传递给
LocalAndDb
(以便LINQ to Entities可以分析代码并将其转换为SQL):

这有点难看,但它不需要在运行时进行低效编译。如果您想要更复杂的解决方案,则可以定义自己的类型以保留预编译函数:

class Precompiled<T1, T2> {
  public Precompiled(Expression<Func<T1, T2>> expr) {
    this.Expression = expr;
    this.Function = expr.Compile();
  }
  public Expression<Func<T1,T2>> Expression { get; private set; }
  public Func<T1,T2> Function { get; private set; }
}
类预编译{
公共预编译(表达式表达式表达式){
this.Expression=expr;
this.Function=expr.Compile();
}
公共表达式{get;private set;}
公共函数{get;private set;}
}

编译成功!谢谢!!说到EF,我完全是个新手。但我现在将对性能方面做一些研究。从你所说的来看,当你“编译”表达式时,不管它是在方法中,还是在签名中,还是在预编译构造函数中,这都会影响性能?@stickman-预编译类的思想是,你可以轻松地构造它一次(调用
编译
一次)然后在对
LocalAndDb
的多个调用中重新创建地使用结果,以便在每次调用期间不会重新编译表达式。
public static object LocalAndDb<T>(this DbSet<T> myTable, 
    Expression<Func<T, bool>> expr) where T : class {
    // ...
    if (item == null) {
        item = myTable.Where(expr).FirstOrDefault();
    }
    return item;
}
public static object LocalAndDb<T>(this DbSet<T> myTable, 
    Func<T, boo> function, Expression<Func<T, bool>> expr) where T : class {
    var item = myTable.Local.Where(o => function((T)o)).FirstOrDefault();
    if (item == null) {
        item = myTable.Where(expr).FirstOrDefault();
    }
    return item;
}

table.LocalAndDb(t => t.Foo > 10, t => t.Foo > 10);
class Precompiled<T1, T2> {
  public Precompiled(Expression<Func<T1, T2>> expr) {
    this.Expression = expr;
    this.Function = expr.Compile();
  }
  public Expression<Func<T1,T2>> Expression { get; private set; }
  public Func<T1,T2> Function { get; private set; }
}