Dynamic Linq Where IN

Dynamic Linq Where IN

如何使用 Dynamic Linq 定义 where in 标准?

我厌倦了下面的解决方法,但它一定行不通,因为它没有意义!

context.Records.Where("@0.Contains(ID)", new object[]{
   new string[] {"1", "2", "3"}
}); // throws error No property or field 'ID' exists in type 'String'

编辑 1:

感谢大家,您只需要在 Dynamic.Linq 查询中使用 itouterIt 关键字,所以在我的示例中我只需要使用 outerIt :

context.Records.Where("@0.Contains(outerIt.ID)", new object[]{
   new string[] {"1", "2", "3"}
});

您可以在此处找到更多示例和信息:Advanced Linq - Dynamic Linq query library: Add support for 'Contains' extension

如果您使用 EF,则可以使用直接 sql 命令,例如:

context.Database.ExecuteSqlCommand($"SELECT * FROM Records AS r WHERE r.{dynamicPropertyName} IN @ids", new string[] {"1", "2", "3"});

编辑

已解决:

System.Linq.Dynamic - Can I use IN clause in WHERE statement

您可以通过创建一个简单的扩展方法轻松获得相同的结果:

public static class Utils
{
    public static bool In<T>(this T src, params T[] items)
    {
        return items.Contains(src);
    }
}

然后这样称呼它:

context.Records.Where(record => record.In("1", "2", "3"));

您可以编写自己的扩展方法In,这里是IEnumerable:

public static class ExtLinq
    {
    public static IEnumerable<TSource> In<TSource, TMember>(this IEnumerable<TSource> source,
            Func<TSource, TMember> identifier, params TMember[] values) =>
         source.Where(m => values.Contains(identifier(m)));
    }

像这样使用它:

context.Records.In(x => x.ID, 1, 2, 3)

如果您希望 IN 在服务器上执行以节省数据传输,请使用此 IQueryable 版本,使用表达式 API:

实现
public static IQueryable<TSource> In<TSource, TMember>(this IQueryable<TSource> source,
   Expression<Func<TSource, TMember>> identifier, params TMember[] values)
        {
            var parameter = Expression.Parameter(typeof(TSource), "m");
            var inExpression = GetExpression(parameter, identifier, values);
            var theExpression = Expression.Lambda<Func<TSource, bool>>(inExpression, parameter);
            return source.Where(theExpression);
        }
static Expression GetExpression<TSource, TMember>(ParameterExpression parameter, Expression<Func<TSource, TMember>> identifier, IEnumerable<TMember> values)
        {
            var memberName = (identifier.Body as MemberExpression).Member.Name;
            var member = Expression.Property(parameter, memberName);
            var valuesConstant = Expression.Constant(values.ToList());
            MethodInfo method = typeof(List<TMember>).GetMethod("Contains");
            Expression call = Expression.Call(valuesConstant, method, member);
            return call;
        }

此查询(或与您的 table 相关的类似查询)将在服务器和 return 所需数据上执行:

SELECT
    [Extent1].[ID] AS [ID],
    [Extent1].[Name] AS [Name]
    FROM [dbo].[Records] AS [Extent1]
    WHERE [Extent1].[ID] IN (1, 2, 3)

这里的其他人介绍了有趣的解决方法,但如果我们使用 Dynamic.Linq 库,它们就没有用了。 亚历山大·纳希尔尼亚克 found this question on Whosebug. There is also a blog post about advanced Linq queries with Dynamic.Linq which reviewdhere.

从版本 1.0.4 开始,库也支持 Contains 扩展。可以像下面这样完成:

 query = Contact.GetContactsList()
                .AsQueryable()
                .Where("@0.Contains(outerIt.Country)", new List<String>() { "Austria", "Poland" }); 

query = Contact.GetContactsList()
               .AsQueryable()
               .Where("@0.Contains(outerIt.Country) && it.BirthDate.Year > @1", new List<string>() { "Austria", "Poland" }, 1955);

有两个关键词itouterIt。它代表您作为参数传递的列表,outerIt 代表集合本身。

这是我的工作示例:

context.Records.Where("@0.Contains(outerIt.ID)", new object[]{
   new string[] {"1", "2", "3"}
});