zoukankan      html  css  js  c++  java
  • 用DynamicMethod提升ORM系统转换业务数据的性能

    在上一篇文章《Sql数据转换为业务数据的几种方法》中提到了ORM系统把Sql数据转换为业务数据的几种方法,但这些方法都不是最佳的方法,后有白菜园等朋友提出用DynamicMethod,发现该方法确实是一个理想的解决方案:

    1、在设计的时候业务实体类的定义非常简洁;

    2、在运行的时候效率比较高,在某些情况下,甚至与硬编码的效率相等。

    3、解偶了数据转换类和业务实体类之间的关系,可以对任意的业务实体类进行转换而不用对他们进行修改。

     

    经过简单测试,发现用DynamicMethod的时间大约是硬编码的1~1.2倍,而用反射所花的时间大约是硬编码和DynamicMethod4~6.5倍。现与大家分享代码,期待能够找到更加好的方法。

    业务实体类User,对应着数据库的Users表:

    public class User

         {

            string _UserID;

           public string UserID

            {

                get { return _UserID; }

                set { _UserID = value; }

            }

     

            string _UserName;

            public string UserName

            {

                get { return _UserName; }

                set { _UserName = value; }

            }

     

            string _Email;

            public string Email

            {

                get { return _Email; }

                set { _Email = value; }

            }

     

            string _Pwd;

            public string Pwd

            {

                get { return _Pwd; }

                set { _Pwd = value; }

            }

    }

     

    用于执行DynamicMethod的委托:

    public delegate T FillBusinessObject<T>(IDataReader AReader);

     

    创建DynamicMethod

    public class BusinessSetter

        {

            static string[] GetFields(string tableName)

            {

                return new String[] { "UserID", "UserName", "Email", "Pwd" };

            }

            public static FillBusinessObject<T> GetFillMethod<T>(string tableName) where T : new()

            {

                Type AType = typeof(T);

                Type[] methodArgs ={ typeof(IDataReader) };

                DynamicMethod AFillMethod = new DynamicMethod("", AType, methodArgs, AType);

                ILGenerator il = AFillMethod.GetILGenerator();

                MethodInfo DataReaderGet = typeof(SqlDataReader).GetMethod("get_Item", new Type[] { typeof(string) });                       

                ConstructorInfo createInfo = AType.GetConstructor(new Type[0]);

                il.DeclareLocal(AType);           

                il.Emit(OpCodes.Newobj, createInfo);

                il.Emit(OpCodes.Stloc_0);

                string[] Fields = GetFields(tableName);

                foreach (string AFieldName in Fields)

                {

                    PropertyInfo AProp = AType.GetProperty(AFieldName);

                    MethodInfo PropSetMethod = AProp.GetSetMethod();

     

                    il.Emit(OpCodes.Ldloc_0);

                    il.Emit(OpCodes.Ldarg_0);

                    il.Emit(OpCodes.Ldstr, AFieldName);

                    il.Emit(OpCodes.Callvirt, DataReaderGet);

                    il.Emit(OpCodes.Isinst, AProp.PropertyType);

                 

                    il.Emit(OpCodes.Callvirt, PropSetMethod);

                }

                il.Emit(OpCodes.Ldloc_0);

                il.Emit(OpCodes.Ret);

     

                return (FillBusinessObject<T>)AFillMethod.CreateDelegate(typeof(FillBusinessObject<T>));

            }    

     }

     

    测试:

    public class Test

        {

            public static void Main()

            {           

                FillBusinessObject<User> AMethod = BusinessSetter.GetFillMethod<User>("Users");

     

                string Sql = "select UserID,UserName,Pwd,Email from Users";

                SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["DbCon"]);

                SqlCommand cmd = new SqlCommand(Sql, con);

                con.Open();

     

                for (int i = 0; i < 5; i++)

                {

                    //DynamicMethod

                    Console.WriteLine("{0}th time:",i+1);

                    SqlDataReader reader = cmd.ExecuteReader();

                    long dynamic = 0;

                    long start = DateTime.Now.Ticks;

                    while (reader.Read())

                    {                   

                        User AUser=AMethod(reader);                   

                    }               

                    long end = DateTime.Now.Ticks;

                    reader.Close();

                    dynamic = end - start;

                    Console.WriteLine("dynamic:{0}", dynamic);               

                                 

                    // Hardcode

                    reader = cmd.ExecuteReader();

                    start = DateTime.Now.Ticks;

                    while (reader.Read())

                    {

                        User AUser = new User();

                        AUser.UserName = reader["UserName"] as string;

                        AUser.Email = reader["Email"] as string;

                        AUser.UserID = reader["UserID"] as string;

                        AUser.Pwd = reader["Pwd"] as string;

                    }

                    end = DateTime.Now.Ticks;

                    reader.Close();               

                    long hardcode = end - start;

                    Console.WriteLine("hardcode:{0}", hardcode);               

     

                    //Reflect

                    reader = cmd.ExecuteReader();               

                    Type UserType=typeof(User);

                    PropertyInfo[] UserInfos ={

                        UserType.GetProperty("UserID"),

                        UserType.GetProperty("UserName"),

                        UserType.GetProperty("Pwd"),

                        UserType.GetProperty("Email")};

     

                    start = DateTime.Now.Ticks;

                    while (reader.Read())

                    {

                        User AUser = new User();

                        foreach (PropertyInfo info in UserInfos)

                            info.SetValue(AUser, reader[info.Name], null);

                    }               

                    end = DateTime.Now.Ticks;

                    reader.Close();

                    long reflect = end - start;

                    Console.WriteLine("reflect:{0}", reflect);

     

                    Console.WriteLine("dynamic/hardcode={0}", (float)dynamic / (float)hardcode);

                    Console.WriteLine("reflect/hardcode={0}", (float)reflect / (float)hardcode);

                    Console.WriteLine("reflect/dynamic={0}", (float)reflect / (float)dynamic);

     

                    Console.WriteLine();

                    Thread.Sleep(50);

                }

                con.Close();

                Console.Read();

            }

    }

    原贴地址:http://www.cnblogs.com/yahong111/archive/2007/08/07/845571.html

  • 相关阅读:
    alpha冲刺—Day8
    alpha冲刺—Day7
    alpha冲刺—冲刺计划&代码规范
    Linux安装jdk
    chrome插件开发-notification API注意事项
    VSCode远程连接Docker
    Idea发布项目到Docker
    开发环境配置
    Java设计模式之《单例模式》及应用场景
    使用Docker安装jenkins
  • 原文地址:https://www.cnblogs.com/zhuawang/p/2142831.html
Copyright © 2011-2022 走看看