我基本上是在尝试构建一个查询,我不知道为什么microsoft在Entity Framework和LINQ中这么难。我有各种参数STRINGS。所以如果你看到一个变量,假设它是从某个地方传入的字符串。
users = this.entities.tableUsers
.Where(searchfield+" LIKE %@0%", search)
.OrderBy(x => x.GetType().GetProperty(order_by).GetValue(x, null).ToString())
.Skip(Convert.ToInt32(limit_begin))
.Take(Convert.ToInt32(limit_end))
.ToList();
我的问题是在LINQ中放入“Where()”函数的内容。
我想搜索字符串为“searchfield”的字段,值为.contains()“search”。
不确定为什么Visual Studio不会让我轻易做到这一点。
我也试过这个,没有运气:
.Where(x => x.GetType().GetProperty(searchfield).GetValue(x, null).ToList().Contains(search))
注意:我不想安装任何新库,这对于现代语言来说应该非常容易和简单。我不介意查询是否返回所有行,然后我用.Contains()搜索它。
答案 0 :(得分:8)
这不是微不足道的,但我相信它可以做到。以下未经过测试。代码来自here。
在
之类的地方创建一个帮助方法public static Expression<Func<T, bool>> GetContainsExpression<T>(string propertyName, string containsValue)
{
var parameterExp = Expression.Parameter(typeof(T), "type");
var propertyExp = Expression.Property(parameterExp, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);
return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
}
public static Expression<Func<T, TKey>> GetPropertyExpression<T, TKey>(string propertyName)
{
var parameterExp = Expression.Parameter(typeof(T), "type");
var exp = Expression.Property(parameterExp, propertyName);
return Expression.Lambda<Func<T, TKey>>(exp, parameterExp);
}
像
一样使用它users = this.entities.tableUsers
.Where(GetContainsExpression<User>(searchfield, search))
.OrderBy(GetPropertyExpression<User, string>(searchfield))
...
<强>更新强>
作为替代方法,您可以创建扩展方法以提供更清晰的语法。在某个静态类中创建以下方法:
public static IQueryable<T> WhereStringContains<T>(this IQueryable<T> query, string propertyName, string contains)
{
var parameter = Expression.Parameter(typeof(T), "type");
var propertyExpression = Expression.Property(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(contains, typeof(string));
var containsExpression = Expression.Call(propertyExpression, method, someValue);
return query.Where(Expression.Lambda<Func<T, bool>>(containsExpression, parameter));
}
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName)
{
var propertyType = typeof(T).GetProperty(propertyName).PropertyType;
var parameter = Expression.Parameter(typeof(T), "type");
var propertyExpression = Expression.Property(parameter, propertyName);
var lambda = Expression.Lambda(propertyExpression, new[] { parameter });
return typeof(Queryable).GetMethods()
.Where(m => m.Name == "OrderBy" && m.GetParameters().Length == 2)
.Single()
.MakeGenericMethod(new[] { typeof(T), propertyType })
.Invoke(null, new object[] { query, lambda }) as IOrderedQueryable<T>;
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName)
{
var propertyType = typeof(T).GetProperty(propertyName).PropertyType;
var parameter = Expression.Parameter(typeof(T), "type");
var propertyExpression = Expression.Property(parameter, propertyName);
var lambda = Expression.Lambda(propertyExpression, new[] { parameter });
return typeof(Queryable).GetMethods()
.Where(m => m.Name == "OrderByDescending" && m.GetParameters().Length == 2)
.Single()
.MakeGenericMethod(new[] { typeof(T), propertyType })
.Invoke(null, new object[] { query, lambda }) as IOrderedQueryable<T>;
}
然后你可以称它们为:
var users = this.entities.tableUsers.WhereStringContains(searchField, search)
.OrderBy(searchField);
答案 1 :(得分:5)
对于现代语言来说,这应该是非常容易和简单的
不,如果它违背了这种语言范式,那就不应该。 LINQ和实体框架(以及任何其他体面的ORM)正是为了避免您要完成的任务而做出的:非类型化和非编译器可验证的查询。所以基本上你就是把方钉钉在圆孔里。
您仍然可以查看Dynamic LINQ。
答案 2 :(得分:2)
您必须构建表达式树以传递给Where
方法。这是对我所说的一些代码的宽松改编:
string searchfield, value; // Your inputs
var param = Expression.Parameter(typeof(User), "user");
return Expression.Lambda<Func<T, bool>>(
Expression.Call(
Expression.Property(
param,
typeof(User).GetProperty(searchfield)),
typeof(string).GetMethod("Contains"),
Expression.Constant(value)),
param);
这将生成一个适当的表达式,用作Where
的参数。
编辑:仅供参考,结果表达式看起来像user => user.Foo.Contains(bar)
。
编辑:要排序,像这样(从我的DynamicOrderList类中翻录):
private IQueryable<T> OrderQuery<T>(IQueryable<T> query, OrderParameter orderBy)
{
string orderMethodName = orderBy.Direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending";
Type t = typeof(T);
var param = Expression.Parameter(t, "user");
var property = t.GetProperty(orderBy.Attribute);
return query.Provider.CreateQuery<T>(
Expression.Call(
typeof(Queryable),
orderMethodName,
new Type[] { t, typeof(string) },
query.Expression,
Expression.Quote(
Expression.Lambda(
Expression.Property(param, property),
param))
));
}
答案 3 :(得分:0)