我有两个 DbSet,Foo 和 Bar。 Foo 有一个标识字符串属性 FooName,而 Bar 有一个标识字符串属性 BarName。
我正在设计一个非常简单的搜索功能,其中用户的查询字词可以等于或包含在标识名称中。
所以我有两种方法(大大简化):
public ActionView SearchFoo(string query)
{
var equalsQuery = db.Foo.Where(f => f.FooName.Equals(query));
var containsQuery = db.Foo.Where(f => f.FooName.Contains(query)).Take(10); // Don't want too many or else a search for "a" would yield too many results
var result = equalsQuery.Union(containsQuery).ToList();
... // go on to return a view
}
public ActionView SearchBar(string query)
{
var equalsQuery = db.Bar.Where(f => f.BarName.Equals(query));
var containsQuery = db.Bar.Where(f => f.BarName.Contains(query)).Take(10); // Don't want too many or else a search for "a" would yield too many results
var result = equalsQuery.Union(containsQuery).ToList();
... // go on to return a view
}
很明显我想要这样的辅助方法:
public IList<T> Search<T>(string query, DbSet<T> set)
{
var equalsQuery = set.Where(f => ???.Equals(query));
var containsQuery = set.Where(f => ???.Contains(query)).Take(10); // Don't want too many or else a search for "a" would yield too many results
var result = equalsQuery.Union(containsQuery).ToList();
... // go on to return a view
}
我最初尝试添加一个 Func<T, string>
到搜索参数,我可以在其中使用 f => f.FooName
和 b => b.BarName
分别,但 LINQ to Entities 在执行查询期间不支持 lambda 表达式。
我一直在摸索如何提取这种重复。
最佳答案
您可以使用 Expression<Funt<T,string>>
实现此目的
public IList<T> Search<T>(string query, DbSet<T> set, Expression<Func<T, string>> propExp)
{
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression someValue = Expression.Constant(query, typeof(string));
MethodCallExpression containsMethodExp =
Expression.Call(propExp.Body, method, someValue);
var e = (Expression<Func<T, bool>>)
Expression.Lambda(containsMethodExp, propExp.Parameters.ToArray());
var containsQuery = set.Where(e).Take(10);
BinaryExpression equalExpression = Expression.Equal(propExp.Body, someValue);
e = (Expression<Func<T, bool>>)
Expression.Lambda(equalExpression, propExp.Parameters.ToArray());
var equalsQuery = set.Where(e);
var result = equalsQuery.Union(containsQuery).ToList();
}
然后你会调用它:
Search ("myValue", fooSet, foo=>foo.FooName);
如果你可以有一个静态方法,那么你可以把它作为一个扩展方法:
public static IList<T> Search<T>(this DbSet<T> set,
string query, Expression<Func<T, string>> propExp)
并称它为:
FooSet.Search ("myValue", foo=>foo.FooName);
关于c# - 当查询仅因属性不同时,如何解决 LINQ to Entity 查询重复问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42883594/