c# - 当查询仅因属性不同时,如何解决 LINQ to Entity 查询重复问题?

标签 c# asp.net-mvc entity-framework linq linq-to-entities

我有两个 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.FooNameb => 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/

相关文章:

c# - 比较大整数列表和小整数列表的最有效方法是什么?

c# - 添加 ASP.NET MVC5 部分 View 时出现异常

asp.net-mvc - ASP.NET MVC EditorTemplate 子文件夹

c# - LINQ to Entities 无法识别方法 'Int32 Parse(System.String)' 方法,

c# - 如何在Visual Studio中为不同的编译宏设置不同的资源?

c# - Ninject - 类库项目中静态类中的内核

jquery - 使用 Kendo Scheduler 创建自定义编辑模板

.net - 插入行时 Entity Framework 和 MySQL 空引用异常

c# - 我应该将通用存储库与 Entity Framework 5 一起使用吗?

c# - Azure 函数遇到 System.Net.Sockets.SocketException