应无所住,而生其心
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2024TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

ef6动态添加条件

11017人阅读 2019/2/10 17:12 总访问:4719738 评论:0 收藏:0 手机
分类: EF


例如我们要匹配一个集合中的所有关键字,我们首先想到的做法是这样的

  public List<Article> GetArtByKeys(List<string> _keywords)
   {
            CNBlog_ServerContext ef = EFHelper.GetInstance();

            var query = ef.Art;
            //循环添加条件
            foreach (string keyword in _keywords)
            {
                query.Where(a => a.Title.Contains(keyword));
            }

            List<Art> articles = query.ToList();

            return arts;
   }

但是这样是不行的,每次都会覆盖到前面的


下面这种写法可以实现动态的and,但是不好实现动态or,这种复杂的条件

var query = context.Article;
var queryable = query.Where(a => a.UserId == userid && a.IsDelete != 1 && a.IsPrivate != 1);
//动态构建条件
foreach (string keyword in _keywords)
{
    queryable = queryable.Where(a => a.Title.Contains(keyword));
}



使用动态组装条件的方法:

  public List<Article> GetArticleByKeys(List<string> _keywords)
   {
            CNBlog_ServerContext ef = EFHelper.GetInstance();

            //先构建一个查询条件
            var predicate = PredicateBuilder.False<Art>();
            foreach (string keyword in _keywords)
            {
                //循环去添加条件
                predicate = predicate.Or(a => a.Title.Contains(keyword));
            }
            List<Article> articles = ef.Art.Where(predicate).ToList();

            return articles;
   }


其中需要的工具类PredicateBuilder代码如下,注意相关的名称空间要引入,因为里边用到了扩展方法

   public static class PredicateBuilder
    {
        public static Expression<Func<T, bool>> True<T>() { return f => true; }
        public static Expression<Func<T, bool>> False<T>() { return f => false; }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                            Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                             Expression<Func<T, bool>> expr2)
        {

            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }
    }



and,or复杂多条件组合方法

例如我们要组合一个这样的复杂一点的条件

p => p.Price > 100 &&
     p.Price < 1000 &&     (p.Description.Contains ("foo") || p.Description.Contains ("far"))

难点在于or外面是有括号的,要和其他两个条件进行and连接,其实知道思路后就不那么难了


思路:

1:先单独构建好or的条件

var inner = PredicateBuilder.False<Product>();
inner = inner.Or (p => p.Description.Contains ("foo"));
inner = inner.Or (p => p.Description.Contains ("far"));

2:在单独构建好and的条件

var outer = PredicateBuilder.True<Product>();
outer = outer.And (p => p.Price > 100);
outer = outer.And (p => p.Price < 1000);

3:把这两个条件进去and连接一下就搞定了!

outer = outer.And (inner);


当然如果不是动态的部分就非常简单了,直接一起写完就好了,比如下面这些条件都是必须要有的

var predicate = PredicateBuilder.False<Article>();
predicate.And(a => a.UserId == uid && a.Title == _article.Title && (a.IsDelete == null || a.IsDelete != 1));

需要根据某些情况动态添加的条件在进行判断添加即可

//ef的动态条件
 if (_article.IsPrivate == 1)
 {
       predicate.And(a => a.IsPrivate == 1);
 }

贴一个多条件的多(2019-9-17 时间会改变太多东西)



参考文章:

http://www.albahari.com/nutshell/predicatebuilder.aspx

欢迎加群讨论技术,群:677373950(满了,可以加,但通过不了),2群:656732739

评价