.NET Core实战项目之CMS 第五章 入门篇-Dapper的快速入门看这篇就够了

写在前面

上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能。今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git命令上传到GitHub上,正好大家可以再次熟悉下Git命令的使用,来巩固上篇文章的知识。本篇文章已经收入.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划 有兴趣的朋友可以加入.NET Core项目实战交流群637326624 进行交流。

作者:依乐祝

原文地址:https://www.cnblogs.com/yilezhu/p/10024091.html

Dapper是什么

Dapper是.NET下一个轻量级的ORM框架,它和Entity Framework或Nhibnate不同,属于轻量级的,并且是半自动的。也就是说实体类都要自己写。它没有复杂的配置文件,一个单文件就可以了。Dapper通过扩展你的IDbConnection来进行工作的。如果你想了解更多内容的话请点击这里

Dapper快速入门

前面几篇文章我们进行介绍的时候都是手动在代码里面创建的模拟数据,这篇文章我们就结合Dapper来从数据库进行相关的操作。为了演示的方便,这里的实例代码我们就使用一个简单地asp.net core控制台程序来进行。

开始前的准备

  1. 在我们的项目文件夹,单击鼠标右键选择“在当前文件夹下面打开Git Bash”

  2. 然后输入git checkout Master 切换回Mater分支,然后输入git checkout -b Sample05 创建一个新的名为“Sample05”的分支,如下所示:

    1543242325029

  3. 使用vs2017创建一个新的项目,名称为“Sample05” 位置位于我们当前的目录,如下图所示:

    1543242490572

  4. 接下来打开数据库,新建一个Content内容表,表结构还沿用之前教程中的实体,这里只给出MSSql的脚本:至于MySql的你自己建了,如果你实在不会的话可以到群里问其他小伙伴要吧

    CREATE TABLE [dbo].[content](
    	[id] [int] IDENTITY(1,1) NOT NULL,[title] [nvarchar](50) NOT NULL,[content] [nvarchar](max) NOT NULL,[status] [int] NOT NULL,[add_time] [datetime] NOT NULL,[modify_time] [datetime] NULL,CONSTRAINT [PK_Content] PRIMARY KEY CLUSTERED 
    (
    	[id] ASC
    )WITH (PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF,IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    
    GO
    
    ALTER TABLE [dbo].[content] ADD  CONSTRAINT [DF_Content_status]  DEFAULT ((1)) FOR [status]
    GO
    
    ALTER TABLE [dbo].[content] ADD  CONSTRAINT [DF_content_add_time]  DEFAULT (getdate()) FOR [add_time]
    GO
    
    CREATE TABLE [dbo].[comment](
    	[id] [int] IDENTITY(1,[content_id] [int] NOT NULL,[content] [nvarchar](512) NOT NULL,CONSTRAINT [PK_comment] PRIMARY KEY CLUSTERED 
    (
    	[id] ASC
    )WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    ALTER TABLE [dbo].[comment] ADD  CONSTRAINT [DF_comment_add_time]  DEFAULT (getdate()) FOR [add_time]
    GO
    
    
  5. 项目中新增数据库表对应的实体对象,代码如下:

        public class Content
        {
            /// <summary>
            /// 主键
            /// </summary>
            public int id { get; set; }
    
            /// <summary>
            /// 标题
            /// </summary>
            public string title { get; set; }
            /// <summary>
            /// 内容
            /// </summary>
            public string content { get; set; }
            /// <summary>
            /// 状态 1正常 0删除
            /// </summary>
            public int status { get; set; }
            /// <summary>
            /// 创建时间
            /// </summary>
            public DateTime add_time { get; set; } = DateTime.Now;
            /// <summary>
            /// 修改时间
            /// </summary>
            public DateTime? modify_time { get; set; }
        }
    public class Comment
        {
            /// <summary>
            /// 主键
            /// </summary>
            public int id { get; set; }
            /// <summary>
            /// 文章id
            /// </summary>
            public int content_id { get; set; }
            /// <summary>
            /// 评论内容
            /// </summary>
            public string content { get; set; }
            /// <summary>
            /// 添加时间
            /// </summary>
            public DateTime add_time { get; set; } = DateTime.Now;
        }
    
  6. 项目中添加Dapper的Nugets包,相信一路看教程过来的你一定知道怎么新增Nuget包吧,这里就不过多介绍了。

    1543243792492

实战演示

  1. 插入操作:将一个对象插入到数据库中,代码如下:

     /// <summary>
            /// 测试插入单条数据
            /// </summary>
           static void test_insert()
            {
                var content = new Content
                {
                    title = "标题1",content = "内容1",};
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"INSERT INTO [Content]
                    (title,[content],status,add_time,modify_time)
    VALUES   (@title,@content,@status,@add_time,@modify_time)";
                    var result = conn.Execute(sql_insert,content);
                    Console.WriteLine($"test_insert:插入了{result}条数据!");
                }
            }
    
  2. 一次批量插入多条数据,测试代码如下:

    /// <summary>
            /// 测试一次批量插入两条数据
            /// </summary>
           static void test_mult_insert()
            {
                List<Content> contents = new List<Content>() {
                   new Content
                {
                    title = "批量插入标题1",content = "批量插入内容1",},new Content
                {
                    title = "批量插入标题2",content = "批量插入内容2",};
    
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"INSERT INTO [Content]
                    (title,contents);
                    Console.WriteLine($"test_mult_insert:插入了{result}条数据!");
                }
            }
    
  3. 执行下代码查看到控制台输出如下的结果:

    1543246862147

    然后到数据库查看下表中的数据如下:

    1543246898729

  4. 下面我们再分别测试下删除一条数据,与一次删除多条数据吧,代码如下:

     /// <summary>
            /// 测试删除单条数据
            /// </summary>
            static void test_del()
            {
                var content = new Content
                {
                    id = 2,};
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"DELETE FROM [Content]
    WHERE   (id = @id)";
                    var result = conn.Execute(sql_insert,content);
                    Console.WriteLine($"test_del:删除了{result}条数据!");
                }
            }
    
            /// <summary>
            /// 测试一次批量删除两条数据
            /// </summary>
            static void test_mult_del()
            {
                List<Content> contents = new List<Content>() {
                   new Content
                {
                    id=3,new Content
                {
                    id=4,};
    
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"DELETE FROM [Content]
    WHERE   (id = @id)";
                    var result = conn.Execute(sql_insert,contents);
                    Console.WriteLine($"test_mult_del:删除了{result}条数据!");
                }
            }
    

    1543247418059

    然后去数据库里查看,发现主键为2,3,4的数据都已经被删除了,如下图所示:

    1543247491525

  5. 下面我们再测试下修改吧,也是分别测试一次只修改一条数据(主键为5),与一次批量修改多条数据(主键为6,7)

    /// <summary>
            /// 测试修改单条数据
            /// </summary>
            static void test_update()
            {
                var content = new Content
                {
                    id = 5,title = "标题5",content = "内容5",};
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"UPDATE  [Content]
    SET         title = @title,[content] = @content,modify_time = GETDATE()
    WHERE   (id = @id)";
                    var result = conn.Execute(sql_insert,content);
                    Console.WriteLine($"test_update:修改了{result}条数据!");
                }
            }
    
            /// <summary>
            /// 测试一次批量修改多条数据
            /// </summary>
            static void test_mult_update()
            {
                List<Content> contents = new List<Content>() {
                   new Content
                {
                    id=6,title = "批量修改标题6",content = "批量修改内容6",new Content
                {
                    id =7,title = "批量修改标题7",content = "批量修改内容7",};
    
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"UPDATE  [Content]
    SET         title = @title,contents);
                    Console.WriteLine($"test_mult_update:修改了{result}条数据!");
                }
            }
    

    现在我们执行下测试代码看下结果吧

    1543248037237

    再到数据库中查看下数据,上步骤5中最后一张图相比较

    1543248094960

  6. 增删改都测试了,下面就开始测试查询吧,我们分别来测试下查询指定的数据以及一次查询多条数据来看下结果吧。还是先上代码,:

     /// <summary>
            /// 查询单条指定的数据
            /// </summary>
            static void test_select_one()
            {
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"select * from [dbo].[content] where id=@id";
                    var result = conn.QueryFirstOrDefault<Content>(sql_insert,new { id=5});
                    Console.WriteLine($"test_select_one:查到的数据为:");
                }
            }
    
            /// <summary>
            /// 查询多条指定的数据
            /// </summary>
            static void test_select_list()
            {
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"select * from [dbo].[content] where id in @ids";
                    var result = conn.Query<Content>(sql_insert,new { ids=new int[] { 6,7} });
                    Console.WriteLine($"test_select_one:查到的数据为:");
                }
            }
    

    然后我们打上断点然后去看下结果吧!这里图片我没有截成功,所以就不贴了。

  7. 关联查询,Dapper的强大之处就在于其关联查询了!为了测试的方便,我们给主键为5的content添加两个comment中,这个插入的代码就不贴出来了,留给大家自行书写吧,如果不会的话可以加群问群里的其他小伙伴吧。这里需要新建一个类

    public class ContentWithCommnet
        {
            /// <summary>
            /// 主键
            /// </summary>
            public int id { get; set; }
    
            /// <summary>
            /// 标题
            /// </summary>
            public string title { get; set; }
            /// <summary>
            /// 内容
            /// </summary>
            public string content { get; set; }
            /// <summary>
            /// 状态 1正常 0删除
            /// </summary>
            public int status { get; set; }
            /// <summary>
            /// 创建时间
            /// </summary>
            public DateTime add_time { get; set; } = DateTime.Now;
            /// <summary>
            /// 修改时间
            /// </summary>
            public DateTime? modify_time { get; set; }
            /// <summary>
            /// 文章评论
            /// </summary>
            public IEnumerable<Comment> comments { get; set; }
        }
    

    然后就是测试代码,运行的查询测试代码如下:查询id为5的文章,文章是包含评论列表的

    代码如下:

    static void test_select_content_with_comment()
            {
                using (var conn = new SqlConnection("Data Source=127.0.0.1;User ID=sa;Password=1;Initial Catalog=Czar.Cms;Pooling=true;Max Pool Size=100;"))
                {
                    string sql_insert = @"select * from content where id=@id;
    select * from comment where content_id=@id;";
                    using (var result = conn.QueryMultiple(sql_insert,new { id = 5 }))
                    {
                        var content = result.ReadFirstOrDefault<ContentWithComment>();
                        content.comments = result.Read<Comment>();
                        Console.WriteLine($"test_select_content_with_comment:内容5的评论数量{content.comments.Count()}");
                    }
    
                }
            }
    

    结果如下所示,调试的代码没法截图我也很无奈。

    1543251360510

GitHub源码

GitHub的测试源码已经上传,https://github.com/yilezhu/Czar.Cms/tree/Sample05 放在Czar.Cms的Sample05分支上面。大家可以参考下,觉得有用的话记得star哦!

总结

本文给大家演示了Dapper的常用方法,不过都是通过同步的方式进行操作的,如果你想使用异步的话可以自行进行测试。文中的大部分内容都有截图,个别调试无法截图的大伙可以自行调试查看!相信通过本文的实例讲解,大伙应该能够使用dapper进行相应的开发!下一篇文章我们将进行vue的讲解!当然也只是进行很浅层次的讲解。因为我是一个后端,也是抱着学习的态度来进行vue的记录的!主要是以快速上为主。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发、订阅和处理的流程。这种实现太简单了,百十行代码就展示了一个基本工作原理。然而,要将这样的解决方案运用到实际生产环境,还有很长的路要走。今天,我们就研究一下在事件处理器中,对象生命周期的管理问题。事实上,不仅仅是在事件处理器
上文已经介绍了Identity Service的实现过程。今天我们继续,实现一个简单的Weather API和一个基于Ocelot的API网关。 回顾 《Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(一)》 Weather API Weather
最近我为我自己的应用开发框架Apworks设计了一套案例应用程序,并以Apache 2.0开源,开源地址是:https://github.com/daxnet/apworks-examples,目的是为了让大家更为方便地学习和使用.NET Core、最新的前端开发框架Angular,以及Apwork
HAL(Hypertext Application Language,超文本应用语言)是一种RESTful API的数据格式风格,为RESTful API的设计提供了接口规范,同时也降低了客户端与服务端接口的耦合度。很多当今流行的RESTful API开发框架,包括Spring REST,也都默认支
在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅、通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件总线的实现。接下来对于事件驱动型架构的讨论,就需要结合一个实际的架构案例来进行分析。在领域驱动设计的讨论范畴,CQRS架构本身就是事件驱动的,因此,
HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单、统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable)更强,并具有自描述的特点。使用了HAL的API会更容易地被第三方开源库所调用,并且使用起来也很方便
何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了。领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architecture Pattern),它也不是一种软件开发方法论,所以,是否应该使用领域驱动设计,以及什么时候使用
《在ASP.NET Core中使用Apworks快速开发数据服务》一文中,我介绍了如何使用Apworks框架的数据服务来快速构建用于查询和管理数据模型的RESTful API,通过该文的介绍,你会看到,使用Apworks框架开发数据服务是何等简单快捷,提供的功能也非常多,比如对Hypermedia的
在上一讲中,我们已经完成了一个完整的案例,在这个案例中,我们可以通过Angular单页面应用(SPA)进行登录,然后通过后端的Ocelot API网关整合IdentityServer4完成身份认证。在本讲中,我们会讨论在当前这种架构的应用程序中,如何完成用户授权。 回顾 《Angular SPA基于
Keycloak是一个功能强大的开源身份和访问管理系统,提供了一整套解决方案,包括用户认证、单点登录(SSO)、身份联合、用户注册、用户管理、角色映射、多因素认证和访问控制等。它广泛应用于企业和云服务,可以简化和统一不同应用程序和服务的安全管理,支持自托管或云部署,适用于需要安全、灵活且易于扩展的用
3月7日,微软发布了Visual Studio 2017 RTM,与之一起发布的还有.NET Core Runtime 1.1.0以及.NET Core SDK 1.0.0,尽管这些并不是最新版,但也已经从preview版本升级到了正式版。所以,在安装Visual Studio 2017时如果启用了
在上文中,我介绍了如何在Ocelot中使用自定义的中间件来修改下游服务的response body。今天,我们再扩展一下设计,让我们自己设计的中间件变得更为通用,使其能够应用在不同的Route上。比如,我们可以设计一个通用的替换response body的中间件,然后将其应用在多个Route上。 O
不少关注我博客的朋友都知道我在2009年左右开发过一个名为Apworks的企业级应用程序开发框架,旨在为分布式企业系统软件开发提供面向领域驱动(DDD)的框架级别的解决方案,并对多种系统架构风格提供支持。这个框架的开发和维护我坚持了很久,一直到2015年,我都一直在不停地重构这个项目。目前这个项目在
好吧,这个题目我也想了很久,不知道如何用最简单的几个字来概括这篇文章,原本打算取名《Angular单页面应用基于Ocelot API网关与IdentityServer4ʺSP.NET Identity实现身份认证与授权》,然而如你所见,这样的名字实在是太长了。所以,我不得不缩写“单页面应用”几个字
在前面两篇文章中,我介绍了基于IdentityServer4的一个Identity Service的实现,并且实现了一个Weather API和基于Ocelot的API网关,然后实现了通过Ocelot API网关整合Identity Service做身份认证的API请求。今天,我们进入前端开发,设计
Ocelot是ASP.NET Core下的API网关的一种实现,在微服务架构领域发挥了非常重要的作用。本文不会从整个微服务架构的角度来介绍Ocelot,而是介绍一下最近在学习过程中遇到的一个问题,以及如何使用中间件(Middleware)来解决这样的问题。 问题描述 在上文中,我介绍了一种在Angu
在大数据处理和人工智能时代,数据工厂(Data Factory)无疑是一个非常重要的大数据处理平台。市面上也有成熟的相关产品,比如Azure Data Factory,不仅功能强大,而且依托微软的云计算平台Azure,为大数据处理提供了强大的计算能力,让大数据处理变得更为稳定高效。由于工作中我的项目
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容。下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了。其中绿色的部分就是上文中新实现的部分,包括一个简单的Event Store,一个事件处理器执行上下文的接
在之前《在ASP.NET Core中使用Apworks快速开发数据服务》一文的评论部分,.NET大神张善友为我提了个建议,可以使用Compile As a Service的Roslyn为语法解析提供支持。在此非常感激友哥给我的建议,也让我了解了一些Roslyn的知识。使用Roslyn的一个很大的好处
很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构。这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地订阅来自于某个渠道的事件消息,并对接收到的消息进行处理,于此同时,它还能够向该渠道发送事件消息,以便