Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用表达式为实体框架生成数组.Contains_C#_Expression Trees - Fatal编程技术网

C# 使用表达式为实体框架生成数组.Contains

C# 使用表达式为实体框架生成数组.Contains,c#,expression-trees,C#,Expression Trees,我希望在Where Contains和Select中都有一个变量字段。“field_a”是我想要成为变量的那个人(有时我想要field_b或_c;它们是字符串)。下面的代码将Select正确构建为Select(x=>x.field\u a)。如何让Where子句的第二部分说,&&targetCodes.Contains(x.field_a)?[db是一个DbContext,itemsArray是一个对象数组,具有名为code的字符串属性] using (var db = dbFactor

我希望在Where Contains和Select中都有一个变量字段。“field_a”是我想要成为变量的那个人(有时我想要field_b或_c;它们是字符串)。下面的代码将Select正确构建为
Select(x=>x.field\u a)
。如何让Where子句的第二部分说,
&&targetCodes.Contains(x.field_a)
?[
db
是一个
DbContext
itemsArray
是一个对象数组,具有名为
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();
    }
使用(var db=dbFactory.CreateInstance())
{
var参数=表达式参数(typeof(myTable),“x”);
var field=Expression.Property(参数“field_a”);
var选择器=表达式.Lambda(字段,参数);
var targetCodes=itemsArray.Select(i=>i.Code.ToArray();
var query=db.myTables
其中(x=>x.companyId==1&&targetCodes.Contains(x.field_a))
.选择((表达式)选择器);
返回wait query.ToArrayAsync();
}

最困难的部分可能是找到
.Contains()
方法的
MethodInfo
。您可以使用
typeof(IEnumerable).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)

有几种方法可以做到这一点。在这种特殊情况下,您甚至不需要处理表达式,因为您可以在
选择
之后简单地使用chain
Where
(chained
Where
条件在最终查询中与
&
组合):

在您的情况下,它可以这样使用:

var containsCall = Expression.Call(
    typeof(Enumerable), nameof(Enumerable.Contains), new [] { typeof(string) },
    Expression.Constant(targetCodes), field);
var query = db.myTables
    .Where(x => x.companyId == 1)
    .Select((Expression<Func<myTable, string>>)selector)
    .Where(v => targetCodes.Contains(v));
public static MethodCallExpression Call(
    Type type,
    string methodName,
    Type[] typeArguments,
    params Expression[] arguments
);
var containsCall = Expression.Call(
    typeof(Enumerable), nameof(Enumerable.Contains), new [] { typeof(string) },
    Expression.Constant(targetCodes), field);