完善主体资料,免费赠送VIP会员!
* 主体类型
* 企业名称
* 信用代码
* 所在行业
* 企业规模
* 所在职位
* 姓名
* 所在行业
* 学历
* 工作性质
请先选择行业
您还可以选择以下福利:
行业福利,领完即止!

下载app免费领取会员

NULL

ad.jpg

二次开发教程:orm 里使用Emit

发布于:2019-07-24 16:33:26

网友投稿

更多

比较一下Emit的赋值,反射赋值和直接赋值的效率


namespace Assignment

{

    class Program

    {

        static SQLiteConnection conn;

        static string dbStr = "test.db";

        static void Main(string[] args)

        {

            CreateDB();

            List<Book> books = new List<Book>();

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

            {

                books.Add(new Book());

            }

            Insert(books);

            Insert(new Book());

 

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            var bs = Query<Book>();

            stopwatch.Stop();

            Console.WriteLine(stopwatch.ElapsedMilliseconds);

 

            stopwatch.Restart();

            var bs1 = QueryEmit<Book>();

            stopwatch.Stop();

            Console.WriteLine(stopwatch.ElapsedMilliseconds);

 

            stopwatch.Restart();

            var bs2 = Query();

            stopwatch.Stop();

            Console.WriteLine(stopwatch.ElapsedMilliseconds);

 

            Console.ReadLine();

        }

 

        static void CreateDB()

        {

            SQLiteConnection.CreateFile(dbStr);

            conn = new SQLiteConnection($"Data Source={dbStr};Version=3;");

            conn.Open();

 

            string sql = "create table book (id int,name varchar(20), price double)";

            SQLiteCommand command = new SQLiteCommand(sql, conn);

            command.ExecuteNonQuery();

        }

        static void Insert(Book book)

        {

            string sql = "insert into book values(@id,@name,@price)";

            SQLiteCommand command = new SQLiteCommand(sql, conn);

            command.Parameters.AddWithValue("id", book.Id);

            command.Parameters.AddWithValue("name", book.Name);

            command.Parameters.AddWithValue("price", book.Price);

 

            command.ExecuteNonQuery();

        }

        static void Insert(IList<Book> books)

        {

            string sql = "insert into book values(@id,@name,@price)";

            var trans = conn.BeginTransaction();

            SQLiteCommand command = new SQLiteCommand(sql, conn, trans);

            foreach (var book in books)

            {

                command.Parameters.Clear();

                command.Parameters.AddWithValue("id", book.Id);

                command.Parameters.AddWithValue("name", book.Name);

                command.Parameters.AddWithValue("price", book.Price);

 

                command.ExecuteNonQuery();

            }

            trans.Commit();

        }

 

        static List<Book> Query()

        {

            List<Book> result = new List<Book>();

            string sql = "select * from book";

            SQLiteCommand command = new SQLiteCommand(sql, conn);

            var reader = command.ExecuteReader();

            while (reader.Read())

            {

                Book book = new Book();

                book.Id = (int)reader.GetValue(0);

                book.Name = (string)reader.GetValue(1);

                book.Price = (double)reader.GetValue(2);

                result.Add(book);

            }

            return result;

        }

 

        static List<T> Query<T>()

        {

            List<T> result = new List<T>();

            string sql = "select * from book";

            SQLiteCommand command = new SQLiteCommand(sql, conn);

            Type type = typeof(T);

            var reader = command.ExecuteReader();

            var readerMap = new ReaderMap(reader);

            var propertyMap = new PropertyMap(readerMap, type);

            while (reader.Read())

            {

                T r = (T)Activator.CreateInstance(type);

                int len = reader.FieldCount;

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

                {

                    propertyMap[i].SetValue(r, reader.GetValue(i));

                }

                result.Add(r);

            }

 

            return result;

        }

        

        static List<T> QueryEmit<T>()

        {

            Type type = typeof(T);

 

            List<T> result = new List<T>();

            string sql = "select * from book";

            SQLiteCommand command = new SQLiteCommand(sql, conn);

            var reader = command.ExecuteReader();

            var readerMap = new ReaderMap(reader);

            var propertyMap = new PropertyMap(readerMap, type);

 

            var func = GetSetter<T>(reader, propertyMap);

 

            while (reader.Read())

            {

                T r = (T)func(reader);

                result.Add(r);

            }

 

            return result;

        }

 

        static Func<SQLiteDataReader, object> GetSetter<T>(SQLiteDataReader reader, PropertyMap map)

        {

            Type bookType = typeof(T);

            var constructor = bookType.GetConstructors().FirstOrDefault();

            DynamicMethod setter = new DynamicMethod("setbook", bookType, new Type[] { typeof(SQLiteDataReader) });

            setter.DefineParameter(0, ParameterAttributes.In, "reader");

 

            var iLGenerator = setter.GetILGenerator();

 

            iLGenerator.DeclareLocal(bookType); //Ldloc_0 book

            iLGenerator.DeclareLocal(typeof(object));//Ldloc_1 reader.GetValue

 

            iLGenerator.Emit(OpCodes.Nop);

            iLGenerator.Emit(OpCodes.Newobj, constructor);

            iLGenerator.Emit(OpCodes.Stloc_0);

            iLGenerator.Emit(OpCodes.Nop);

 

            var getM = typeof(DbDataReader).GetMethod("GetValue");

 

            int len = map.Count;

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

            {

                ///读数据

                iLGenerator.Emit(OpCodes.Ldarg_0);

                iLGenerator.Emit(OpCodes.Ldc_I4, i);

                iLGenerator.Emit(OpCodes.Callvirt, getM);

                iLGenerator.Emit(OpCodes.Stloc_1);

                iLGenerator.Emit(OpCodes.Nop);

 

                var tp = map[i];

                iLGenerator.Emit(OpCodes.Ldloc_0);

                iLGenerator.Emit(OpCodes.Ldloc_1);

                if (tp.PropertyType.IsValueType)

                    iLGenerator.Emit(OpCodes.Unbox_Any, tp.PropertyType);

                else

                    iLGenerator.Emit(OpCodes.Castclass, tp.PropertyType);

 

                var mt = tp.GetSetMethod();

 

                iLGenerator.Emit(OpCodes.Callvirt, mt);

                iLGenerator.Emit(OpCodes.Nop);

            }

 

            iLGenerator.Emit(OpCodes.Ldloc_0);

            iLGenerator.Emit(OpCodes.Ret);

 

            return (Func<SQLiteDataReader, object>)setter.CreateDelegate(typeof(Func<SQLiteDataReader,object>));

        }

 

        static Book QueryBook(SQLiteDataReader reader)

        {

            Book book = new Book();

            book.Id = (int)reader.GetValue(0);

            book.Name = (string)reader.GetValue(1);

            book.Price = (double)reader.GetValue(2);

            return book;

        }

    }

    public class PropertyMap

    {

        private PropertyInfo[] properties = null;

        public PropertyMap(ReaderMap readerMap,Type type)

        {

            int len = readerMap.Count;

            Count = len;

            var ps = type.GetProperties();

            properties = new PropertyInfo[len];

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

            {

                var readerItem = readerMap[i];

                var tp = ps.FirstOrDefault(p => p.Name.ToUpper() == readerItem.Name.ToUpper());

                if (tp != null)

                {

                    if (tp.PropertyType.IsAssignableFrom(readerItem.Type))

                    {

                        properties[i] = tp;

                    }

                }                

            }

        }

        public PropertyInfo this[int i]

        {

            get

            {

                return properties[i];

            }

        }

        public int Count { get; private set; }

    }

    public class ReaderMap

    {

        private ReaderItem[] items = null; 

        public ReaderMap(SQLiteDataReader reader)

        {

            int len = reader.FieldCount;

            Count = len;

            items = new ReaderItem[len];

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

            {

                items[i] = new ReaderItem

                {

                    Id = i,

                    Name = reader.GetName(i),

                    Type = reader.GetFieldType(i)

                };

            }

        }

        public int Count

        {

            get;

            private set;

        }

        public ReaderItem this[int i]

        {

            get

            {

                return items[i];

            }

        }

    }

    public class ReaderItem

    {

        public int Id { get; set; }

        public string Name { get; set; }

        public Type Type { get; set; }

    }

    public class Book

    {

        public int Id { get; set; }

        public string Name { get; set; }

        public double Price { get; set; }

        public Book()

        {

            Id = 0;

            Name = "Name";

            Price = 11.9;

        }

 

        public override string ToString()

        {

            return $"Id; {Id}\tName: {Name}\tPrice: {Price}";

        }

    }

}

输出结果为


反射时间2725


Emit 时间1745


直接赋值1604

本文版权归腿腿教学网及原创作者所有,未经授权,谢绝转载。

未标题-1.jpg

上一篇:二次开发教程:Dapper里使用Attribute自定义映射关系

下一篇:二次开发教程:Emit 循环

60acb4e0ef112.png