Dapper.NET—轻量ORM

Dapper.NET使用

本文目录
  • Dapper.NET使用
  • 1、为什么选择Dapper
  • 2、以Dapper(4.0)为例。
  • 2.1 在数据库中建立几张表。
  • 2.2实体类。
  • 3.使用方法
  • 3.1  一对一映射
  • 3.2 一对多映射
  • 3.3 插入实体
  • 3.4 执行存储过程

Dapper是一款轻量级ORM工具(Github)。如果你在小的项目中,使用Entity Framework、NHibernate 来处理大数据访问及关系映射,未免有点杀鸡用牛刀。你又觉得ORM省时省力,这时Dapper 将是你不二的选择。

访问量不大的项目可以考虑用EF写数据库操作,因为EF除了速度上慢以外,但开发效率极快,省略了很多sql写法,并能很方便的调用外键、集合等信息,用EF写项目最爽的事。

不过有些项目网站要考虑运行速度,这时不得不用其它的ORM框架,比如用Dapper,因为它速度快,而且写sql非常灵活。

EF-------重量级ORM的代表

优点:

  • 面向对象式操作数据库。
  • 完全摆脱SQL 语句,不用关心SQL如何写,可移植性强。
  • 支持code first,开发人员可以完成且无需关心数据库,代码先行,极大节省开发成本。
  • 结合LINQ,开发效率高。
  • 跨数据库,易配置。
  • 与VS结合较好。

缺点:

  • 比较复杂,学习曲线复杂(官方文档丰富且杂)。
  • 不适合做统计查询(因为统计查询需要执行查询效率高)。
  • 对于多表查询或一些复杂的查询实现较为困难和复杂。
  • 自动生成的SQL语句复杂,效率低。
  • EF的Context上下文不是线程安全的(知识有限,不懂)。
  • 包和插件较为冗余(对于中小型项目来说),性能一般。

Dapper--------轻量级ORM的代表

优点:

  • 开源,轻巧(轻量级),编译后文件简单且小巧。
  • 支持主流数据库,MSSQL,MySQL,Oracle。
  • 执行效率高。
  • 学习较为方便

缺点:

  • 半自动ORM,需要开发人员自己写实体类(可以借助实体类生成工具生成)。
  • 开发时间成本高,LINQ支持较弱。
  • 维护成本高,不支持Code first,开发人员除了要维护数据库中的表,还需要维护代码表中的映射对象。

1、为什么选择Dapper

  1. 轻量。只有一个文件(SqlMapper.cs),编译完成之后只有120k(好象是变胖了)
  2. 速度快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
  3. 支持多种数据库。Dapper可以在所有Ado.net Providers下工作,包括sqlite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server
  4. 可以映射一对一,一对多,多对多等多种关系。
  5. 性能高。通过Emit反射IDataReader的序列队列,来快速的得到和产生对象,性能不错。
  6. 支持FrameWork2.0,3.0,3.5,4.0,4.5
  7. Dapper语法十分简单。并且无须迁就数据库的设计

2、以Dapper(4.0)为例

 先通过NuGet进行安装Dapper 

PM> Install-Package Dapper -Version 1.40.0

 2.1 在数据库中建立几张表

CREATE TABLE [dbo].[CICUser]
(
    [UserId]                [int] IDENTITY(1, 1) PRIMARY KEY NOT NULL,
    [Username]              [nvarchar](256) NOT NULL,
    [PasswordHash]          [nvarchar](500) NULL,
    [Email]                 [nvarchar](256) NULL,
    [PhoneNumber]           [nvarchar](30) NULL,
    [IsFirstTimeLogin]      [bit] DEFAULT(1) NOT NULL,
    [AccessFailedCount]     [int] DEFAULT(0) NOT NULL,
    [CreationDate]          [datetime] DEFAULT(GETDATE()) NOT NULL,
    [IsActive]              [bit] DEFAULT(1) NOT NULL
)

CREATE TABLE [dbo].[CICRole]
(
    [RoleId]       [int] IDENTITY(1, 1) PRIMARY KEY NOT NULL,
    [RoleName]     [nvarchar](256) NOT NULL,
)

CREATE TABLE [dbo].[CICUserRole]
(
     [Id]   [int] IDENTITY(1, 1) PRIMARY KEY NOT NULL,
     [UserId]  [int] FOREIGN KEY REFERENCES [dbo].[CICUser] ([UserId]) NOT NULL,
     [RoleId]  [int] FOREIGN KEY REFERENCES [dbo].[CICRole] ([RoleId]) NOT NULL
)

2.2 实体类

在创建实体类时,属性名称一定要与数据库字段一一对应。

public class User
{
        public User()
        {
            Role = new List<Role>();
        }
        public int UserId { get; set; }
        public string UserName { get; set; }       
        public string Password { get; set; }
        public string Email { get; set; }
        public string PhoneNumber { get; set; }
        public bool IsFirstTimeLogin { get; set; }
        public int AccessFailedCount { get; set; }
        public DateTime CreationDate { get; set; }
        public bool IsActive { get; set; }
        public List<Role> Role { get; set; }
}
public class Role
{
        public int RoleId { get; set; }
        public string RoleName { get; set; }
}
public class Customer
{
        public int UserId { get; set; }
        public string UserName { get; set; }       
        public string Password { get; set; }
        public string Email { get; set; }
        public string PhoneNumber { get; set; }
        public bool IsFirstTimeLogin { get; set; }
        public int AccessFailedCount { get; set; }
        public DateTime CreationDate { get; set; }
        public bool IsActive { get; set; }
        public Role Role { get; set; }
}    

3. 使用方法

3.1  一对一映射

private static void OneToOne(string sqlConnectionString)
{
            List<Customer> userList = new List<Customer>();
            using (IDbConnection conn = GetSqlConnection(sqlConnectionString))
            {
                string sqlCommandText = @"SELECT c.UserId,c.Username AS UserName,
                    c.PasswordHash AS [Password],c.Email,c.PhoneNumber,c.IsFirstTimeLogin,c.AccessFailedCount,
                    c.CreationDate,c.IsActive,r.RoleId,r.RoleName 
                    FROM dbo.CICUser c WITH(NOLOCK) 
                    INNER JOIN CICUserRole cr ON cr.UserId = c.UserId 
                    INNER JOIN CICRole r ON r.RoleId = cr.RoleId";
                userList = conn.Query<Customer, Role, Customer>(sqlCommandText, 
                                                                (user, role) => { user.Role = role; return user; },
                                                                null,
                                                                null,
                                                                true, 
                                                                "RoleId", 
                                                                null,
                                                                null).ToList();
            }

            if (userList.Count > 0)
            {
                userList.ForEach((item) => Console.WriteLine("UserName:" + item.UserName +
                                                             "----Password:" + item.Password + 
                                                             "-----Role:" + item.Role.RoleName +
                                                             "\n"));

                Console.ReadLine();
            }
}

3.2 一对多映射

private static void OneToMany(string sqlConnectionString)
{
            Console.WriteLine("One To Many");
            List<User> userList = new List<User>();

            using (IDbConnection connection = GetSqlConnection(sqlConnectionString))
            {

                string sqlCommandText3 = @"SELECT c.UserId,
                    c.Username      AS UserName,
                    c.PasswordHash  AS [Password],
                    c.Email,
                    c.PhoneNumber,
                    c.IsFirstTimeLogin,
                    c.AccessFailedCount,
                    c.CreationDate,
                    c.IsActive,
                    r.RoleId,
                    r.RoleName
                    FROM   dbo.CICUser c WITH(NOLOCK)
                    LEFT JOIN CICUserRole cr
                    ON  cr.UserId = c.UserId
                    LEFT JOIN CICRole r
                    ON  r.RoleId = cr.RoleId";

                var lookUp = new Dictionary<int, User>();
                userList = connection.Query<User, Role, User>(sqlCommandText3,
                    (user, role) =>
                    {
                        User u;
                        if (!lookUp.TryGetValue(user.UserId, out u))
                        {
                            lookUp.Add(user.UserId, u = user);
                        }
                        u.Role.Add(role);
                        return user;
                    }, null, null, true, "RoleId", null, null).ToList();
                var result = lookUp.Values;
            }

            if (userList.Count > 0)
            {
                userList.ForEach((item) => Console.WriteLine("UserName:" + item.UserName +
                                             "----Password:" + item.Password +
                                             "-----Role:" + item.Role.First().RoleName +
                                             "\n"));

                Console.ReadLine();
            }
            else
            {
                Console.WriteLine("No Data In UserList!");
            }
}

3.3 插入实体

public static void InsertObject(string sqlConnectionString)
{
            string sqlCommandText = @"INSERT INTO CICUser(Username,PasswordHash,Email,PhoneNumber) VALUES (@UserName,@Password,@Email,@PhoneNumber)";
            using (IDbConnection conn = GetSqlConnection(sqlConnectionString))
            {
                User user = new User();
                user.UserName = "Dapper";
                user.Password = "654321";
                user.Email = "Dapper@infosys.com";
                user.PhoneNumber = "13795666243";
                int result = conn.Execute(sqlCommandText, user);
                if (result > 0)
                {
                    Console.WriteLine("Data have already inserted into DB!");
                }
                else
                {
                    Console.WriteLine("Insert Failed!");
                }

                Console.ReadLine();
            }
}

3.4 执行存储过程 

        /// <summary>
        /// Execute StoredProcedure and map result to POCO
        /// </summary>
        /// <param name="sqlConnnectionString"></param>
        public static void ExecuteStoredProcedure(string sqlConnnectionString)
        {
            List<User> users = new List<User>();
            using (IDbConnection conn = GetSqlConnection(sqlConnnectionString))
            {
                users = conn.Query<User>("dbo.p_getUsers", 
                                        new { UserId = 2 },
                                        null, 
                                        true, 
                                        null, 
                                        CommandType.StoredProcedure).ToList();
            }
            if (users.Count > 0)
            {
                users.ForEach((user) => Console.WriteLine(user.UserName + "\n"));
            }
            Console.ReadLine();
        }
        /// <summary>
        /// Execute StroedProcedure and get result from return value
        /// </summary>
        /// <param name="sqlConnnectionString"></param>
        public static void ExecuteStoredProcedureWithParms(string sqlConnnectionString)
        {
            DynamicParameters p = new DynamicParameters();
            p.Add("@UserName", "cooper");
            p.Add("@Password", "123456");
            p.Add("@LoginActionType", null, DbType.Int32, ParameterDirection.ReturnValue);
            using (IDbConnection conn = GetSqlConnection(sqlConnnectionString))
            {
                conn.Execute("dbo.p_validateUser", p, null, null, CommandType.StoredProcedure);
                int result = p.Get<int>("@LoginActionType");
                Console.WriteLine(result);
            }

            Console.ReadLine();
        }

 3.5 插入后返回新插入的数据行主键值(自动增长的主键) 

string query = @"INSERT INTO dbo.CalfFeed_CalfIsleLine (LineName,LineNumber,
        CreatorUserId,Creator,CreationTime,LastModifierUserId,Modifier,LastModificationTime) 
        VALUES (@LineName,@LineNumber,@CreatorUserId,
        @Creator,@CreationTime,@LastModifierUserId,@Modifier,@LastModificationTime);
        SELECT * FROM dbo.CalfFeed_CalfIsleLine WHERE CalfIsleLine_Id = CAST(SCOPE_IDENTITY() as int);";
  using (IDbConnection conn = GetSqlConnection(sqlConnectionString))
  {              
       //int result = conn.Execute(query, obj);
       var objNew = conn.Query<CalfFeed_CalfIsleLine>(query, obj).FirstOrDefault();
       int count = objNew == null ? 0 : 1;
       int id = objNew == null ? 0 : objNew.CalfIsleLine_Id;
  }

 

posted @ 2018-09-27 15:21  以德为先  阅读(1174)  评论(0编辑  收藏  举报