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
查询中使用 it
或 outerIt
关键字,所以在我的示例中我只需要使用 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);
有两个关键词it
和outerIt
。它代表您作为参数传递的列表,outerIt
代表集合本身。
这是我的工作示例:
context.Records.Where("@0.Contains(outerIt.ID)", new object[]{
new string[] {"1", "2", "3"}
});
如何使用 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
查询中使用 it
或 outerIt
关键字,所以在我的示例中我只需要使用 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);
有两个关键词it
和outerIt
。它代表您作为参数传递的列表,outerIt
代表集合本身。
这是我的工作示例:
context.Records.Where("@0.Contains(outerIt.ID)", new object[]{
new string[] {"1", "2", "3"}
});