程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# ORM中Dto Linq Expression 和 數據庫Model Linq Expression之間的轉換,

C# ORM中Dto Linq Expression 和 數據庫Model Linq Expression之間的轉換,

編輯:C#入門知識

C# ORM中Dto Linq Expression 和 數據庫Model Linq Expression之間的轉換,


今天在百度知道中看到一個問題,研究了一會便回答了:

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)就可以了。

性能方面沒有測試,應該是可以使用緩存的。有興趣的朋友可以改一下。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved