首页 > 学院 > 开发设计 > 正文

C#ORM中DtoLinqExpression和数据库ModelLinqExpression之间的转换

2019-11-14 14:02:03
字体:
来源:转载
供稿:网友

今天在百度知道中看到一个问题,研究了一会便回答了:

http://zhidao.baidu.com/question/920461189016484459.html

如何使dto linq 表达式转换到数据库实体对象linq表达式。自己搜集了一些资料然后实战了一下,还是可行。

自己扩展的一个方法 Cast<TInput, TToPRoperty>(this Expression<Func<TInput, bool>> expression),代码如下:

namespace System{    public static class LambdaExpressionExtensions    {        private static Expression Parser(ParameterExpression parameter, Expression expression)        {            if (expression == null) return null;            switch (expression.NodeType)            {                //一元运算符                case ExpressionType.Negate:                case ExpressionType.NegateChecked:                case ExpressionType.Not:                case ExpressionType.Convert:                case ExpressionType.ConvertChecked:                case ExpressionType.ArrayLength:                case ExpressionType.Quote:                case ExpressionType.TypeAs:                    {                        var unary = expression as UnaryExpression;                        var exp = Parser(parameter, unary.Operand);                        return Expression.MakeUnary(expression.NodeType, exp, unary.Type, unary.Method);                    }                //二元运算符                case ExpressionType.Add:                case ExpressionType.AddChecked:                case ExpressionType.Subtract:                case ExpressionType.SubtractChecked:                case ExpressionType.Multiply:                case ExpressionType.MultiplyChecked:                case ExpressionType.Divide:                case ExpressionType.Modulo:                case ExpressionType.And:                case ExpressionType.AndAlso:                case ExpressionType.Or:                case ExpressionType.OrElse:                case ExpressionType.LessThan:                case ExpressionType.LessThanOrEqual:                case ExpressionType.GreaterThan:                case ExpressionType.GreaterThanOrEqual:                case ExpressionType.Equal:                case ExpressionType.NotEqual:                case ExpressionType.Coalesce:                case ExpressionType.ArrayIndex:                case ExpressionType.RightShift:                case ExpressionType.LeftShift:                case ExpressionType.ExclusiveOr:                    {                        var binary = expression as BinaryExpression;                        var left = Parser(parameter, binary.Left);                        var right = Parser(parameter, binary.Right);                        var conversion = Parser(parameter, binary.Conversion);                        if (binary.NodeType == ExpressionType.Coalesce && binary.Conversion != null)                        {                            return Expression.Coalesce(left, right, conversion as LambdaExpression);                        }                        else                        {                            return Expression.MakeBinary(expression.NodeType, left, right, binary.IsLiftedToNull, binary.Method);                        }                    }                //其他                case ExpressionType.Call:                    {                        var call = expression as MethodCallExpression;                        List<Expression> arguments = new List<Expression>();                        foreach (var argument in call.Arguments)                        {                            arguments.Add(Parser(parameter, argument));                        }                        var instance = Parser(parameter, call.Object);                        call = Expression.Call(instance, call.Method, arguments);                        return call;                    }                case ExpressionType.Lambda:                    {                        var Lambda = expression as LambdaExpression;                        return Parser(parameter, Lambda.Body);                    }                case ExpressionType.Memberaccess:                    {                        var memberAccess = expression as MemberExpression;                        if (memberAccess.Expression == null)                        {                            memberAccess = Expression.MakeMemberAccess(null, memberAccess.Member);                        }                        else                        {                            var exp = Parser(parameter, memberAccess.Expression);                            var member = exp.Type.GetMember(memberAccess.Member.Name).FirstOrDefault();                            memberAccess = Expression.MakeMemberAccess(exp, member);                        }                        return memberAccess;                    }                case ExpressionType.Parameter:                    return parameter;                case ExpressionType.Constant:                    return expression;                case ExpressionType.TypeIs:                    {                        var typeis = expression as TypeBinaryExpression;                        var exp = Parser(parameter, typeis.Expression);                        return Expression.TypeIs(exp, typeis.TypeOperand);                    }                default:                    throw new Exception(string.Format("Unhandled expression type: '{0}'", expression.NodeType));            }        }        public static Expression<Func<TToProperty, bool>> Cast<TInput, TToProperty>(this Expression<Func<TInput, bool>> expression)        {            var p = Expression.Parameter(typeof(TToProperty), "p");            var x = Parser(p, expression);            return Expression.Lambda<Func<TToProperty, bool>>(x, p);        }    }}

比如有如下的 实体类对象:

    public class User    {        public int Id { get; set; }        public string Name { get; set; }    }    public class UserDto    {        public int Id { get; set; }        public string Name { get; set; }    }

简单的测试代码:

    class Program    {        static int[] array0 = new[] { 0, 1 };        static void Main1(string[] args)        {            var array1 = new[] { 0, 1 };            Expression<Func<UserDto, bool>> exp = null;            Expression<Func<User, bool>> exp2 = null;            //====exp====            //exp = u => u.Name == "张三";            //exp = u => u.Id.Equals(1);            //exp = u => u.Id.Equals(1) && u.Name == "张三";            //exp = u => u.Id.Equals(1) && u.Name == "张三" || u.Name == "张三";            //exp = u => Filter(u.Name);            //exp = u => !Filter(u.Name);            //exp = u => u.Id.Equals(1) && u.Name == "张三" && Filter(u.Name);            //exp = u => array1.Contains(u.Id);            //exp = u => array1.Contains(u.Id) || u.Name == "张三";            //exp = u => array0.Contains(u.Id);            //exp = u => u.Id > 0;            //exp = u => u.Id < 10;            //exp = u => u.Id * 2 < 10;            //exp = u => u.Id - 2 < 10;            //exp = u => u.Id + 2 < 10;            //exp = u => u.Id / 2 < 10;            //exp = u => (int)(u.Id / 2) < 10;            //exp = u => u.Name is string;            //exp = u => ((object)u.Id).ToString() == "1";            //exp = u => u.Id == default(int);            //exp = u => true;            //exp = u => Math.Abs(u.Id)==1;            exp = u =>                        u.Id.Equals(1)                        && u.Name == "张三"                        && u.Id < 10                        && array1.Contains(u.Id)                        && u.Id + 2 < 10                        && (((object)u.Id).ToString() == "1" || u.Name.Contains(""))                        && Math.Abs(u.Id) == 1                        && Filter(u.Name)                        && true                        ;            //=====exp2=====            exp2 = exp.Cast<UserDto, User>();            Console.WriteLine(exp.ToString());            Console.WriteLine(exp.ToString());            //测试数据            List<User> list = new List<User>() {                 new User{ Id=0,Name="AAA"},                new User{ Id=1,Name="张三"},                new User{ Id=2,Name="李四"}            };            var item = list.Where(exp2.Compile()).FirstOrDefault();            Console.WriteLine(item.Name);            Console.ReadKey();        }        public static bool Filter(string name)        {            return name.Contains("");        }    }

应该说常用的筛选条件都是支持的。这里的list由于没有数据库环境就用List<User>模拟的,真实ORM环境换成list.Where(exp2)就可以了。

性能方面没有测试,应该是可以使用缓存的。有兴趣的朋友可以改一下。

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表