c# - 使用表达式为 Entity Framework 构建 Array.Contains

标签 c# expression-trees

我想在 Where-Contains 和 Select 中都有一个变量字段。 “field_a”是我想要可变的人(有时我想要 field_b 或 _c;它们是字符串)。下面的代码正确构建了 Select as Select(x => x.field_a)。如何让 Where 子句的第二部分说 && targetCodes.Contains(x.field_a)? [db 是一个 DbContextitemsArray 是一个对象数组,这些对象具有名为 Code 的字符串属性。]

    using (var db = dbFactory.CreateInstance())
    {
        var parameter = Expression.Parameter(typeof(myTable), "x");
        var field = Expression.Property(parameter, "field_a");
        var selector = Expression.Lambda(field, parameter);
        var targetCodes = itemsArray.Select(i => i.Code).ToArray();
        var query = db.myTables
            .Where(x => x.companyId == 1 && targetCodes.Contains(x.field_a))
            .Select((Expression<Func<myTable, string>>)selector);
        return await query.ToArrayAsync();
    }

最佳答案

可能最困难的部分是找到 MethodInfo.Contains()方法。你可以使用 typeof(IEnumerable<string>).GetMethod(...).Where(...) ,但对于具有多个重载的泛型方法,通常很难做到正确。这是一个小技巧,它使用 C# 编译器通过创建临时表达式为您找到正确的重载:

Expression<Func<IEnumerable<string>, bool>> containsExpr = (IEnumerable<string> q) => q.Contains((string)null);
var containsMethod = (containsExpr.Body as MethodCallExpression).Method;
// containsMethod should resolve to this overload:
// System.Linq.Enumerable.Contains<string>(IEnumerable<string>, string)

程序的其余部分只是通过调用适当的 Expression.XYZ() 来构建表达式方法:

var companyIdEquals1 = Expression.Equal(
    Expression.Property(parameter, nameof(myTable.companyId)),
    Expression.Constant(1));

var targetCodesContains = Expression.Call(
    containsMethod,
    Expression.Constant(targetCodes),
    field/*reuses expression you already have*/);

var andExpr = Expression.And(companyIdEquals1, targetCodesContains);
var whereExpr = (Expression<Func<myTable, bool>>)Expression.Lambda(andExpr, parameter);

var query = db//.myTables
    .Where(whereExpr)
    .Select((Expression<Func<myTable, string>>)selector);

关于c# - 使用表达式为 Entity Framework 构建 Array.Contains,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52285648/

相关文章:

C# - 正则表达式替换(如果不在引号内)

c# - 如何组合(或)两个表达式树

c# - 继承时的表达式推断

c# - 将平面线性树表示转换为内存树表示

linq - ERROR 静态方法需要空实例,非静态方法需要非空实例

c# - 如何使用方法调用生成已编译的 lambda?

c# - 如何在 C# 中从 api 解析奇怪的 json 对象

c# - 改DBML,如何改SQL数据库?

c# - 当属性隐藏具有 'new' 关键字的继承成员时,反射如何告诉我?

c# - 如何用 Moq 测试 void 方法?