Linq-EF中的自定义扩展方法等同于SQL“IN”子句

时间:2017-09-25 13:27:35

标签: c# sql-server string entity-framework linq

我正在尝试创建一个自定义Linq to Entities扩展方法,该方法采用逗号分隔的字符串,将其转换为数组,然后使用IEnumerable<string>.Contains生成等效的SQL IN子句。

当您始终知道要将此过滤器应用于的表/实体及其列/属性时,这很容易。挑战在于我希望能够在任何实体或属性上使用此扩展方法。

这是我走了多远:

public static IQueryable<TSource> CustomInClause<TSource>(this IQueryable<TSource> myQuery, Expression<Func<TSource, string>> colExpression, string filterCriteria)
{
    string[] myArray = filterCriteria.Split(",", StringSplitOptions.RemoveEmptyEntries);

    //Various other operations here..............

    if (myArray.Length > 0)
    {
        myQuery = myQuery.Where(b => myArray.Contains(colExpression));
    }

    return myQuery;
}

正如您所看到的,我正在尝试将colExpression用作动态表达式,它将等同于x => x.SomeColumn,其中SomeColumn可以是任何字符串/ varchar列。

然后我会像这样实现这个扩展:

var q = context.SomeTable.CustomInClause(f => f.SomeColumn, someString);

var q2 = context.OtherTable.CustomInCluse(f => f.OtherColumn, otherString);

现在我收到此错误:

  

'string []'不包含'Contains'和最佳的定义   扩展方法重载   “ParallelEnumerable.Contains&GT;&GT;(ParallelQuery&GT;&gt;中   表达式&gt;)'需要类型的接收器   'ParallelQuery&GT;&GT;'

我不太确定如何在此实例中使用并行查询,或者是否有其他解决方案。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

您必须在where子句

中构建Contains调用作为表达式的一部分
var myArray = filterCriteria.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
               .ToList();   
var containsExp = Expression.Call(Expression.Constant(myArray), 
                                    "Contains", null, colExpression.Body);

if (myArray.Count > 0)
{
    myQuery = myQuery.Where(Expression.Lambda<Func<TSource, bool>>
                                        (containsExp, colExpression.Parameters));
}

return myQuery;

在这种情况下,List优于Array,因为list有Contains函数,而Array只有扩展名