Чтобы сделать это, вам нужно передать лямбда-выражение в LocalAndDb
в виде дерева выражений (чтобы LINQ to Entities мог анализировать код и переводить его в SQL):
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;
}
Тогда, конечно, проблема в том, что вы не можете выполнить дерево выражений при проверке данных в памяти. Одним из способов решения этой проблемы является использование Compile
метода Expression<T>
, но это будет немного неэффективно (в зависимости от вашего сценария).
Другой вариант - передать условие как дерево функций и выражений:
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; }
}