zoukankan      html  css  js  c++  java
  • 轻量级ORM框架初探-Dapper与PetaPoco的基本使用

    一、EntityFramework

      EF是传统的ORM框架,也是一个比较重量级的ORM框架。这里仍然使用EF的原因在于为了突出轻量级ORM框架的性能,所谓有对比才有更优的选择。

    1.1 准备一张数据库表

      (1)For MSSQL

    CREATE TABLE [dbo].[Posts]
    (
        [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
        [CategoryId] INT NOT NULL, 
        [Slug] VARCHAR(120) NOT NULL,  
        [Title] NVARCHAR(100) NOT NULL, 
        [Published] DATETIME NOT NULL,
        [Excerpt] NVARCHAR(MAX) NOT NULL, 
        [Content] NVARCHAR(MAX) NOT NULL
    );

      (2)For MySQL

    CREATE TABLE Posts
    (
        Id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
        CategoryId INT NOT NULL, 
        Slug VARCHAR(120) NOT NULL,  
        Title NVARCHAR(100) NOT NULL, 
        Published DATETIME NOT NULL,
        Excerpt LONGTEXT NOT NULL, 
        Content LONGTEXT NOT NULL
    );

    1.2 使用Model First方式创建数据模型

      (1)通过nuget添加EF组件引用,然后创建edmx数据模型

      (2)由于EF首次使用存在效率问题,因此采用园子里推荐的EF暖机操作作为测试首次执行的代码

        static void WarmupEntityFramework()
        {
            // EF暖机操作
            using (var db = new MyAppDBContext())
            {
                var objectContext = ((IObjectContextAdapter)db).ObjectContext;
                var mappingCollection = (System.Data.Entity.Core.Mapping.StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(System.Data.Entity.Core.Metadata.Edm.DataSpace.CSSpace);
                mappingCollection.GenerateViews(new System.Collections.Generic.List<System.Data.Entity.Core.Metadata.Edm.EdmSchemaError>());
            }
        } 

      (3)写一个读取数据的方法,遍历读取Posts表记录(该表有1万行记录)

        static void ModelFirstReadPosts()
        {
            var dbContext = new MyAppDBContext();
            foreach (var item in dbContext.Posts)
            {
                Console.WriteLine("ID:{0},Title:{1}", item.Id, item.Title);
            }
        } 

      (4)编写入口方法,通过Stopwatch记录测试耗时

        class Program
        {
            static Program()
            {
                WarmupEntityFramework();
            }
    
            static void Main(string[] args)
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                // EF:4.9s
                ModelFirstReadPosts();
                watch.Stop();
                Console.WriteLine("Time consumed : {0} ms", watch.ElapsedMilliseconds);
    
                Console.ReadKey();
            }
    
            #region Method01.EntityFramework暖机操作
            static void WarmupEntityFramework()
            {
                // EF暖机操作
                using (var db = new MyAppDBContext())
                {
                    var objectContext = ((IObjectContextAdapter)db).ObjectContext;
                    var mappingCollection = (System.Data.Entity.Core.Mapping.StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(System.Data.Entity.Core.Metadata.Edm.DataSpace.CSSpace);
                    mappingCollection.GenerateViews(new System.Collections.Generic.List<System.Data.Entity.Core.Metadata.Edm.EdmSchemaError>());
                }
            } 
            #endregion
    
            #region Method02.Model First方式读取数据库表记录
            static void ModelFirstReadPosts()
            {
                var dbContext = new MyAppDBContext();
                foreach (var item in dbContext.Posts)
                {
                    Console.WriteLine("ID:{0},Title:{1}", item.Id, item.Title);
                }
            } 
            #endregion
        }
    View Code

      F5调试运行,首次查询结果如下图所示:

      五次查询之后平均耗时:4.9s

    二、Dapper

    2.1 关于Dapper

      Dapper是一个开源轻的量级的ORM,只有一个代码文件,完全开源,你可以放在项目里的任何位置,来实现数据到对象的ORM操作,体积小速度快。 

    2.2 使用Dapper

      (1)通过nuget添加Dapper组件

      (2)针对MSSQL的查询和新增操作

        #region Method01.读取MSSQL单张表
        // 2.7s
        static void DapperReadPosts()
        {
            using (SqlConnection connection = new SqlConnection(connStr))
            {
                var postList = connection.Query<Post>("select * from Posts");
                foreach (var item in postList)
                {
                    Console.WriteLine("ID:{0},Title:{1}", item.Id, item.Title);
                }
            }
        }
        #endregion
    
        #region Method02.读取MSSQL连接查询
        // 2.6s
        static void DapperReadJoin()
        {
            using (SqlConnection connection = new SqlConnection(connStr))
            {
                // 这里查询结果是动态语言类型
                var postList = connection.Query("select Id,Title,GETDATE() as PostDate from Posts");
                foreach (var item in postList)
                {
                    Console.WriteLine("ID:{0},PostDate:{1}", item.Id, item.PostDate);
                }
            }
        }
        #endregion
    
        #region Method03.读取MSSQL多个结果集
        // 2.8s
        static void DapperReadMultiResultSet()
        {
            using (SqlConnection connection = new SqlConnection(connStr))
            {
                using (var reader = connection.QueryMultiple("select * from Posts;select 1000 as Number;"))
                {
                    var postList = reader.Read<Post>();
                    foreach (var item in postList)
                    {
                        Console.WriteLine("ID:{0},Title:{1}", item.Id, item.Title);
                    }
                }
            }
        }
        #endregion
    
        #region Method04.插入MSSQL新记录
        // 0.37s
        static void InsertPostRecord()
        {
            using (SqlConnection connection = new SqlConnection(connStr))
            {
                // 多次插入单条记录
                int count = connection.Execute("insert into Posts values(@CategoryId, @Slug, @Title, @Published, @Excerpt, @Content);", new { CategoryId = 10, Slug = "BOOK", Title = "大话设计模式", Published = DateTime.Now.AddDays(1), Excerpt = "ChengJie", Content = "Design Patterns" });
                Console.WriteLine("受影响行数:{0}", count);
    
                count = connection.Execute("insert into Posts values(@CategoryId, @Slug, @Title, @Published, @Excerpt, @Content);", new Post() { CategoryId = 10, Slug = "BOOK", Title = "大话数据结构", Published = DateTime.Now.AddDays(1), Excerpt = "ChengJie", Content = "Data Structure" });
    
                Console.WriteLine("受影响行数:{0}", count);
    
                // 一次插入多条记录
                IList<Post> postRecords = new List<Post>();
                postRecords.Add(new Post() { CategoryId = 10, Slug = "BOOK", Title = "构建之法-现代软件工程", Published = DateTime.Now.AddDays(1), Excerpt = "ZouXin", Content = "Software Engineering" });
                postRecords.Add(new Post() { CategoryId = 10, Slug = "BOOK", Title = "编程之美", Published = DateTime.Now.AddDays(1), Excerpt = "ZouXin", Content = "I Love Coding" });
                count = connection.Execute("insert into Posts values(@CategoryId, @Slug, @Title, @Published, @Excerpt, @Content);", postRecords);
    
                Console.WriteLine("受影响行数:{0}", count);
            }
        }
        #endregion
    View Code

      ① 棒棒哒的地方1:读取多表连接查询

            // 这里查询结果是动态语言类型
            var postList = connection.Query("select Id,Title,GETDATE() as PostDate from Posts");
            foreach (var item in postList)
            {
                Console.WriteLine("ID:{0},PostDate:{1}", item.Id, item.PostDate);
            }

      ② 棒棒哒的地方2:读取多个查询结果集

            using (var reader = connection.QueryMultiple("select * from Posts;select 1000 as Number;"))
            {
                var postList = reader.Read<Post>();
                foreach (var item in postList)
                {
                    Console.WriteLine("ID:{0},Title:{1}", item.Id, item.Title);
                }
            }

      ③ 棒棒哒的地方3:一次插入多条数据记录

        // 一次插入多条记录
        IList<Post> postRecords = new List<Post>();
        postRecords.Add(new Post() { CategoryId = 10, Slug = "BOOK", Title = "构建之法-现代软件工程", Published = DateTime.Now.AddDays(1), Excerpt = "ZouXin", Content = "Software Engineering" });
        postRecords.Add(new Post() { CategoryId = 10, Slug = "BOOK", Title = "编程之美", Published = DateTime.Now.AddDays(1), Excerpt = "ZouXin", Content = "I Love Coding" });
        count = connection.Execute("insert into Posts values(@CategoryId, @Slug, @Title, @Published, @Excerpt, @Content);", postRecords);

      ④ 如何跨数据库读取数据记录:依赖于抽象,不依赖于具体

        static void GetPostsCrossMultiDB()
        {
            // 依赖于抽象,不依赖于具体
            using (IDbConnection connection = DbProviderFactories.GetFactory(connSetting.ProviderName).CreateConnection())
            {
                connection.ConnectionString = connSetting.ConnectionString;
                // 使用标准SQL语句屏蔽差异
                var postList = connection.Query<Post>("select * from Posts");
                foreach (var item in postList)
                {
                    Console.WriteLine("ID:{0},Title:{1}", item.Id, item.Title);
                }
            }
        } 

      (3)测试结果:

    方法 耗时
    读取MSSQL单张表 2.7s
    读取MSSQL连接查询 2.6s
    读取MSSQL多个结果集 2.8s
    多次插入MSSQL新记录 148ms

    三、PetaPoco

    3.1 关于PetaPoco

      PetaPoco是一款适用于.NET应用程序的轻型对象关系映射器。与那些功能完备的ORM(如NHibernate或Entity Framework)不同的是,PetaPoco更注重易用性和性能,而非丰富的功能。使用PetaPoco只需要引入一个C#文件,可以使用强类型的 POCO(Plain Old CLR Object),并支持使用T4模板生成的类等等。

    3.2 使用PetaPoco

      (1)通过nuget添加PetaPoco组件

      (2)编辑Database.tt模板文件,前提是首先将连接字符串配置正确

      (3)针对MSSQL的读取和插入操作

        private static void ReadAllPostData()
        {
            using (var context = new MyAppDBContext())
            {
                var postList = context.Query<Post>("select * from Posts");
                foreach (var item in postList)
                {
                    Console.WriteLine("ID:{0},Title:{1}", item.Id, item.Title);
                }
            }
        }
    
        private static void InsertNewPostData()
        {
            var post = new Post
            {
                CategoryId = 1,
                Slug = "BOOK",
                Title = "Microsoft SQL Server 2008技术内幕",
                Content = Guid.NewGuid().ToString(),
                Excerpt = Guid.NewGuid().ToString(),
                Published = DateTime.Now
            };
    
            var count = post.Insert();
    
            Console.WriteLine("受影响行数:{0}", count);
        }
    View Code

      (4)测试结果:

    方法 耗时
    读取MSSQL单张表 2.7s
    插入MSSQL新纪录 30ms

    SourceCode

    (1)ORMDemo:http://pan.baidu.com/s/1pJAEf0n

    Reference

    (1)Dapper.NET:https://github.com/StackExchange/dapper-dot-net

  • 相关阅读:
    Enterprise Library 4.1 Data Access Block 快速使用图文笔记
    敏捷开发(名字起得很帅,很忽悠人)原则 括号里面加了自己的理解笔记
    与弟弟谈话的摘要
    练习:选头像控件
    [转]保护你的flash(as3)程序基于socket方式传送swf文件
    Silverlight 又多了一套skin
    Silverlight制作逐帧动画
    Silverlight Spy 2 源代码查看器
    跨平台开发silverlight
    Silverlight 2 搜索照片 Live
  • 原文地址:https://www.cnblogs.com/edisonchou/p/4854036.html
Copyright © 2011-2022 走看看