Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 简洁的IPredicate到linq转换_C#_Dapper - Fatal编程技术网

C# 简洁的IPredicate到linq转换

C# 简洁的IPredicate到linq转换,c#,dapper,C#,Dapper,在我的应用程序中,我有一些类实现了一个公共接口,我们称之为IValidator。 实现这种接口的每个类都返回PredicateGroup对象。所以为了测试的目的,我 决定从数据库的特定视图中获取所有数据,然后从返回的集合(IEnumerable)中获取这些数据 通过linq where进行快速过滤(无需使用不同的谓词多次调用数据库) dapper是否支持从IPredicate/PredicateGroup到Func的这种转换,还是有另一种更快/更好的解决方案 下面是我想要实现的一个小演示:

在我的应用程序中,我有一些类实现了一个公共接口,我们称之为IValidator。 实现这种接口的每个类都返回PredicateGroup对象。所以为了测试的目的,我 决定从数据库的特定视图中获取所有数据,然后从返回的集合(IEnumerable)中获取这些数据 通过linq where进行快速过滤(无需使用不同的谓词多次调用数据库)

dapper是否支持从IPredicate/PredicateGroup到Func的这种转换,还是有另一种更快/更好的解决方案

下面是我想要实现的一个小演示:

        IEnumerable<Products> products = null;
        using (var cn = new SqlConnection("connectionstring"))
        {
            //Get all elemnts from database(using only one call)
            products = cn.GetList<Products>(Predicates.Field<Products>(f => f.Discontinued, Operator.Eq, true));
        }

        // class which implement IValidator and returns predicate group
        List<IPredicate> computerPredicates = new List<IPredicate>
        {
            Predicates.Field<Products>(f => f.ProductName, Operator.Eq, "Computer"),
            Predicates.Field<Products>(f => f.Price, Operator.Eq, 1200)
        };
        var computerPredicatesGroup = new PredicateGroup {Predicates = computerPredicates };

        // class which implement IValidator and returns predicate group
        List<IPredicate> phonePredicates = new List<IPredicate>
        {
            Predicates.Field<Products>(f => f.ProductName, Operator.Eq, "Phone"),
            Predicates.Field<Products>(f => f.Price, Operator.Eq, 400)
        };
        var phonePredicatesGroup = new PredicateGroup { Predicates = phonePredicates };

        var computers = products.Where( /* computerPredicates */); //??
        var phones = products.Where( /* phonePredicatesGroup */); //??
IEnumerable products=null;
使用(var cn=new-SqlConnection(“connectionstring”))
{
//从数据库获取所有元素(仅使用一个调用)
products=cn.GetList(Predicates.Field(f=>f.contracted,Operator.Eq,true));
}
//类,该类实现IValidator并返回谓词组
List computerPredicates=新列表
{
谓词.Field(f=>f.ProductName,Operator.Eq,“计算机”),
谓词.Field(f=>f.Price,Operator.Eq,1200)
};
var computerPredicatesGroup=new PredicateGroup{Predicates=computerPredicates};
//类,该类实现IValidator并返回谓词组
List phonePredicates=新列表
{
Predicates.Field(f=>f.ProductName,Operator.Eq,“Phone”),
谓词.Field(f=>f.Price,Operator.Eq,400)
};
var phonePredicatesGroup=new PredicateGroup{Predicates=phonePredicates};
var computers=产品。其中(/*computerPredicates*/);/??
var phones=产品。其中(/*phonePredicatesGroup*/);/??

我没有找到任何解决方案,所以我决定编写自己的解析器

示例如何使用它:

测试模型:

    class TestCarModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Model { get; set; }
        public string Type { get; set; }
        public float Cost { get; set; }
    }

    private List<TestCarModel> PrepareTestData()
    {
        return new List<TestCarModel>()
        {
            new TestCarModel(){ Id = 1, Name = "Fiat", Model = "500", Type = "Kompakt", Cost = 20000 },
            new TestCarModel(){ Id = 2, Name = "Fiat", Model = "Bravo", Type = "Kompakt", Cost = 30000 },
            new TestCarModel(){ Id = 3, Name = "Opel", Model = "Astra", Type = "Sedan", Cost = 20000 },
            new TestCarModel(){ Id = 4, Name = "Honda", Model = "Civic", Type = "Hatchback", Cost = 15000 },
            new TestCarModel(){ Id = 5, Name = "Audi", Model = "A4", Type = "Sedan", Cost = 40000 },
        };
    }
var groupPredicate = new PredicateGroup
{
    Operator = GroupOperator.Or,
    Predicates = new List<IPredicate>()
};

var predicateGroup1 = new PredicateGroup
{
    Operator = GroupOperator.Or,
    Predicates = new List<IPredicate>()
    {
        Predicates.Field<TestCarModel>(f => f.Model, Operator.Eq, "500"),
        Predicates.Field<TestCarModel>(f => f.Model, Operator.Eq, "Bravo")
    }
};

var predicateGroup2 = new PredicateGroup
{
    Operator = GroupOperator.Or,
    Predicates = new List<IPredicate>()
    {
        Predicates.Field<TestCarModel>(f => f.Name, Operator.Eq, "Opel"),
        Predicates.Field<TestCarModel>(f => f.Type, Operator.Eq, "Hatchback"),
    }
};

groupPredicate.Predicates.Add(Predicates.Field<TestCarModel>(f => f.Cost, Operator.Gt, 35000));
groupPredicate.Predicates.Add(predicateGroup1);
groupPredicate.Predicates.Add(predicateGroup2);


var testdata = PrepareTestData();
var expression = PredicateParser<TestCarModel>.Parse(groupPredicate).Compile();
var result = testdata.Where(expression);
var predicates = new List<IPredicate>
{
    Predicates.Field<TestCarModel>(f => f.Type, Operator.Eq, "Sedan"),
    Predicates.Field<TestCarModel>(f => f.Type, Operator.Eq, "Hatchback"),
};

var testdata = PrepareTestData();
var expression = PredicateParser<TestCarModel>.ParseOr(predicates).Compile();
var result = testdata.Where(expression);
合成器

    public class CompositeIterator<T>
    {
        private Expression<Func<T, bool>> finalQuery;
        private Expression<Func<T, bool>> higherQuery;
        private GroupOperator? previousOperator;
        private int level = -1;

        public Expression<Func<T, bool>> Prepare(PredicateGroup predicateGroup)
        {
            previousOperator = predicateGroup.Operator;
            finalQuery = t => predicateGroup.Operator == GroupOperator.And;
            CallRecursive(predicateGroup);
            return finalQuery;
        }

        private void CallRecursive(PredicateGroup predicateGroup)
        {
            var nodes = predicateGroup.Predicates;
            bool isSet = true;
            ++level;

            foreach (var n in nodes)
            {
                if (n is PredicateGroup @group)
                {                  
                    CallRecursive(@group);
                    --level;
                }
                else
                {
                    var expr = PredicateParser<T>.Parse((IFieldPredicate)n);

                    if (level > 0)
                    {
                        if (isSet)
                        {
                            higherQuery = t => predicateGroup.Operator == GroupOperator.And;
                            isSet = false;
                        }

                        higherQuery = predicateGroup.Operator == GroupOperator.And
                                    ? higherQuery.And(expr)
                                    : higherQuery.Or(expr);
                    }
                    else
                    {
                        previousOperator = predicateGroup.Operator;

                        finalQuery = predicateGroup.Operator == GroupOperator.And
                                    ? finalQuery.And(expr)
                                    : finalQuery.Or(expr);
                    }
                }
            }

            if (higherQuery != null)
            {
                finalQuery = previousOperator == GroupOperator.And
                            ? finalQuery.And(higherQuery)
                            : finalQuery.Or(higherQuery);
            }

            higherQuery = null;
        }
    }
公共类合成器
{
私有表达式最终查询;
私有表达式高级查询;
私有组操作员?以前的操作员;
私有整数级别=-1;
公共表达式准备(谓词组谓词组)
{
previousOperator=谓词组运算符;
finalQuery=t=>predicateGroup.Operator==GroupOperator.And;
CallRecursive(谓词组);
返回最终查询;
}
私有void CallRecursive(谓词组谓词组)
{
var节点=谓词组谓词;
bool-isSet=true;
++水平;
foreach(节点中的变量n)
{
if(n是PredicateGroup@group)
{                  
CallRecursive(@group);
--水平;
}
其他的
{
var expr=PredicateParser.Parse((IFieldPredicate)n);
如果(级别>0)
{
如果(isSet)
{
higherQuery=t=>predicateGroup.Operator==GroupOperator.And;
isSet=假;
}
higherQuery=predicateGroup.Operator==GroupOperator.And
?高级查询和(expr)
:高级查询。或(expr);
}
其他的
{
previousOperator=谓词组运算符;
finalQuery=predicateGroup.Operator==GroupOperator.And
?最终查询和(expr)
:finalQuery.Or(expr);
}
}
}
if(higherQuery!=null)
{
finalQuery=previousOperator==GroupOperator.And
?最终查询和(高级查询)
:finalQuery.Or(高级查询);
}
higherQuery=null;
}
}
    public static class PredicateBuilder
    {
        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);
            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);
            return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }
    }
    public static class LikeExpression
    {
        private static readonly MethodInfo ApplyLikeMethodInfo = typeof(LikeExpression).GetMethod("ApplyLike");
        private static readonly MethodInfo ApplyLikeNoCaseMethodInfo = typeof(LikeExpression).GetMethod("ApplyLikeNoCase");
        private static readonly MethodInfo ApplyNotLikeMethodInfo = typeof(LikeExpression).GetMethod("ApplyNotLike");
        private static readonly MethodInfo ApplyNotLikeNoCaseMethodInfo = typeof(LikeExpression).GetMethod("ApplyNotLikeNoCase");

        public static Expression Like(Expression lhs, Expression pattern, bool caseSensitive = false)
        {
            return caseSensitive
                ? Expression.Call(ApplyLikeMethodInfo, lhs, pattern)
                : Expression.Call(ApplyLikeNoCaseMethodInfo, lhs, pattern);
        }

        public static Expression NotLike(Expression lhs, Expression pattern, bool caseSensitive = false)
        {
            return caseSensitive
                ? Expression.Call(ApplyNotLikeMethodInfo, lhs, pattern)
                : Expression.Call(ApplyNotLikeNoCaseMethodInfo, lhs, pattern);
        }

        public static bool ApplyLike(string text, string likePattern)
        {
            string pattern = PatternToRegex(likePattern);
            return Regex.IsMatch(text, pattern, RegexOptions.None);
        }

        public static bool ApplyLikeNoCase(string text, string likePattern)
        {
            string pattern = PatternToRegex(likePattern);
            return Regex.IsMatch(text, pattern, RegexOptions.IgnoreCase);
        }

        public static bool ApplyNotLike(string text, string likePattern)
        {
            string pattern = PatternToRegex(likePattern);
            return !Regex.IsMatch(text, pattern, RegexOptions.None);
        }

        public static bool ApplyNotLikeNoCase(string text, string likePattern)
        {
            string pattern = PatternToRegex(likePattern);
            return !Regex.IsMatch(text, pattern, RegexOptions.IgnoreCase);
        }

        public static string PatternToRegex(string pattern)
        {
            pattern = Regex.Escape(pattern);
            pattern = pattern.Replace("%", @".*");
            pattern = $"^{pattern}$";

            return pattern;
        }
    }
    public class CompositeIterator<T>
    {
        private Expression<Func<T, bool>> finalQuery;
        private Expression<Func<T, bool>> higherQuery;
        private GroupOperator? previousOperator;
        private int level = -1;

        public Expression<Func<T, bool>> Prepare(PredicateGroup predicateGroup)
        {
            previousOperator = predicateGroup.Operator;
            finalQuery = t => predicateGroup.Operator == GroupOperator.And;
            CallRecursive(predicateGroup);
            return finalQuery;
        }

        private void CallRecursive(PredicateGroup predicateGroup)
        {
            var nodes = predicateGroup.Predicates;
            bool isSet = true;
            ++level;

            foreach (var n in nodes)
            {
                if (n is PredicateGroup @group)
                {                  
                    CallRecursive(@group);
                    --level;
                }
                else
                {
                    var expr = PredicateParser<T>.Parse((IFieldPredicate)n);

                    if (level > 0)
                    {
                        if (isSet)
                        {
                            higherQuery = t => predicateGroup.Operator == GroupOperator.And;
                            isSet = false;
                        }

                        higherQuery = predicateGroup.Operator == GroupOperator.And
                                    ? higherQuery.And(expr)
                                    : higherQuery.Or(expr);
                    }
                    else
                    {
                        previousOperator = predicateGroup.Operator;

                        finalQuery = predicateGroup.Operator == GroupOperator.And
                                    ? finalQuery.And(expr)
                                    : finalQuery.Or(expr);
                    }
                }
            }

            if (higherQuery != null)
            {
                finalQuery = previousOperator == GroupOperator.And
                            ? finalQuery.And(higherQuery)
                            : finalQuery.Or(higherQuery);
            }

            higherQuery = null;
        }
    }