LINQ 是否可以动态添加 where 子句

问题描述 投票:0回答:6

我想用不同的键搜索我的数据库。根据输入的情况,可能有1个键到10个键。有没有办法动态地将 OR/AND 子句添加到我的 Linq 查询中?

 keys[k] // I have my keys in this array 
 var feedList = (from feed in ctx.Feed
                 where feed.content.contains(keys[0]) 
                       && feed.content.contains(keys[1])
                       && ... // continues with the keys.length
                 select new {
                    FeedId = feed.DuyuruId,
                    FeedTitle = feed.FeedTitle,
                    FeedContent = feed.FeedContents,
                    FeedAuthor = user.UserName + " " +User.UserSurname
 }
c# linq entity-framework where-clause
6个回答
14
投票

您可以尝试使用

.All
子句来检查所有键:

where keys.All(key => feed.content.contains(key))

7
投票

对于 AND 子句来说很简单:

var feedList = from feed in ctx.Feed;
foreach(var key in keys){
    feedList = feedList.Where(x=> content.contains(key));
}
var resultQuery = feedList.Select(x=> new {....});

对于 OR,您需要使用

Expressions
或尝试 LinqKit 及其谓词:

var predicate = PredicateBuilder.False<TypeOfYourEntity>();
foreach(var key in keys){
    predicate = predicate.Or(x=> content.contains(key));
}
var resultQuery = ctx.Feed.Where(predicate).Select(x=> new {....});

3
投票

可以使用LINQ的扩展方法

ctx.Feed.Where(f => {  
//Your logic here
if(something != null){
      return f.Property == something
  } 
}).Select( new { FeedId = feed.DuyuruId,
                    FeedTitle = feed.FeedTitle,
                    FeedContent = feed.FeedContents,
                    FeedAuthor = user.UserName + " " +User.UserSurname })

2
投票

你可以做这样的事情。请记住,这可能会带来一些开销

 var students = ctx.Students;

 if (!String.IsNullOrWhiteSpace(SearchParams.Name))
      students = from s in students where s.Name.StartsWith(SearchParams.Name)

 if (!String.IsNullOrWhiteSpace(SearchParams.Surname))
      students = from s in students where s.Surname.StartsWith(SearchParams.Surname)

2
投票

我想提供一个示例,说明 @mellamokb 的答案如何适用于我的场景,以可能帮助任何需要相当动态的

linq
查询的人。

在我的示例中,我只是对

datatable
类进行了扩展,这样我就可以检查数据库中是否存在一行数据,这样就不会抛出
SQL
主键异常。

/// <summary>
/// 
/// </summary>
/// <param name="DT"></param>
/// <param name="ColumnNames">Columns to check in affected table.</param>
/// <param name="ItemtoChecks">Values to check in affected column.</param>
/// <returns></returns>
public static bool TableContains(this DataTable DT, string[] ColumnNames, object[] ItemtoChecks)
{
  var result = from row in DT.AsEnumerable()
               where ColumnNames.All(
               r => row.Field<object>(r).ToString() == Convert.ToString(
                 ItemtoChecks[ColumnNames.ToList()
                 .FindIndex(p => p.Equals(r, StringComparison.OrdinalIgnoreCase))]))
               select row;                   
  return (result.Count() > 0);
}

此方法允许您向

string[]
添加所需数量的列名称以及相应的值以签入单独的
object[]
。查询检查
datatable
,如果找到匹配,则该方法返回
true
,如果没有,则返回
false


0
投票

如果您需要“OR”或其他复杂性,您可以使用Expression类。 检查这个答案: https://stackoverflow.com/a/78770748/5063739

public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
    var q = db.ProductDetail.Where(BuildFilter(productGroupName,productTypeName)).Orderby(c=>c.ProductTypeName);
    return q;
}

private static Expression<Func<ProductDetail, bool>> BuildFilter(string productGroupName, string productTypeName)
{
    var p = Expression.Parameter(typeof(ProductDetail));
    return Expression.Lambda<Func<ProductDetail, bool>>(
        Expression.AndAlso(
            Expression.Equal(
                Expression.Property(p, "productGroupName"),
                Expression.Constant(productGroupName)
                ),
            Expression.OrElse(
                Expression.Equal(
                    Expression.Property(p, "productTypeName"),
                    Expression.Constant(productTypeName.ToLower())
                    ),
                Expression.Equal(
                    Expression.Property(p, "productTypeName"),
                    Expression.Constant(productTypeName)
                    )
                )
            ),
            p
        );
}

这相当于

c.ProductGroupName == productGroupName 
 && (c.ProductTypeName == productTypeName.toLower()
     || c.ProductTypeName == productTypeName
    )
© www.soinside.com 2019 - 2024. All rights reserved.