国产化中的 .NET Core 操作达梦数据库DM8的两种方式(操作详解)

目录
  • 背景
  • 环境
  • SDK
  • 操作数据库
    • DbHelperSQL方式
    • Dapper方式

背景

某个项目需要实现基础软件全部国产化,其中操作系统指定银河麒麟,数据库使用达梦V8,CPU平台的范围包括x64、龙芯、飞腾、鲲鹏等。考虑到这些基础产品对.NET的支持,最终选择了.NET Core 3.1。

环境

  • CPU平台:x86-64 / Arm64
  • 操作系统:银河麒麟 v4
  • 数据库:DM8
  • .NET:.NET Core 3.1

SDK

达梦自己提供了.NET操作其数据库的SDK,可以通过NuGet安装,也可以通过安装达梦数据库获取。因为NuGet上的版本不知道是谁提供的,所以这里以安装数据库获取相关SDK为例。

在官网下载DM8的数据库安装文件:https://www.dameng.com/list_103.html

下载前需要先登录,随便注册一个帐号就好了。

这里需要选择CPU和操作系统,按照你的开发环境选择即可,下载后按照提示安装。

这里以Windows10为例,安装后SDK文件的位置在:C:\dmdbms\drivers\dotNet

这里边有EF的SDK,也有NHibernate的SDK,不过这篇文章只使用最基础的基于ADO.NET的SDK。

这些SDK在文件夹DmProvider下边,这里还提供了一个Nuget包,可以放到自己的Nuget仓库中,方便内部安装。

可以看到,这个SDK可以支持.NET Core2.0以上的所有.NET版本。

操作数据库

这里提供两种方式:传统的DbHelperSQL方式 和 Dapper 方式。

DbHelperSQL方式

这种方式早年用的比较多,现在还有很多项目在使用,通过定义一组工具方法包装对数据库的各种增删改查操作。下面给出代码:

 public class DmDbClient
    {
        private string connectionString = string.Empty;

        /// <summary>
        /// 初始化DMClient的一个新实例
        /// </summary>
        /// <param name="str"></param>
        public DmDbClient(string str)
        {
            connectionString = str;
        }
        #region 通用快捷方法
        /// 执行一条SQL语句,确定记录是否存在
        /// <param name="sql">SQL查询语句</param>
        /// <returns></returns>
        public bool Exists(string sql)
            object obj = GetSingle(sql);
            int cmdresult;
            if (Equals(obj, null) || Equals(obj, DBNull.Value))
            {
                cmdresult = 0;
            }
            else
                cmdresult = int.Parse(obj.ToString());
            return cmdresult > 0;
        public async Task<bool> ExistsAsync(string sql)
            object obj = await GetSingleAsync(sql);
        /// <param name="paras">SQL参数数组</param>
        public bool Exists(string sql, params DmParameter[] paras)
            object obj = GetSingle(sql, paras);
            if ((object.Equals(obj, null)) || (object.Equals(obj, DBNull.Value)))
        public async Task<bool> ExistsAsync(string sql, params DmParameter[] paras)
            object obj = await GetSingleAsync(sql, paras);
        /// 获取记录条数
        /// <param name="tableName">表名</param>
        /// <param name="sqlCondition">查询条件</param>
        public int GetCount(string tableName, string sqlCondition)
            string sql = "select count(1) from `" + tableName + "`";
            if (!string.IsNullOrWhiteSpace(sqlCondition))
                sql += " where " + sqlCondition;
            object result = GetSingle(sql);
            if (result != null)
                return Convert.ToInt32(result);
                return 0;
        public async Task<int> GetCountAsync(string tableName, string sqlCondition)
            object result = await GetSingleAsync(sql);
        public int GetCount(string tableName, string sqlCondition, DmParameter[] paras)
            object result = GetSingle(sql, paras);
        public async Task<int> GetCountAsync(string tableName, string sqlCondition, DmParameter[] paras)
            object result = await GetSingleAsync(sql, paras);
        #endregion 通用快捷方法
        #region 执行简单SQL语句
        /// 执行SQL语句,返回影响的记录数
        /// <param name="sql">SQL语句</param>
        /// <returns>影响的记录数</returns>
        public int ExecuteSql(string sql)
            using (DmConnection connection = new DmConnection(connectionString))
                using (DmCommand cmd = new DmCommand(sql, connection))
                {
                    connection.Open();
                    int rows = cmd.ExecuteNonQuery();
                    return rows;
                }
        public async Task<int> ExecuteSqlAsync(string sql)
                    await connection.OpenAsync();
                    int rows = await cmd.ExecuteNonQueryAsync();
        /// 执行SQL语句,返回影响的记录数(可自定义超时时间)
        /// <param name="timeout">执行超时时间</param>
        public int ExecuteSqlByTime(string sql, int timeout)
            using (DmConnection connection = new DmConnection(this.connectionString))
                    cmd.CommandTimeout = timeout;
        public async Task<int> ExecuteSqlByTimeAsync(string sql, int timeout)
        /// 执行多条SQL语句,实现数据库事务。
        /// <param name="sqlList">多条SQL语句</param>
        public void ExecuteSqlTrans(ArrayList sqlList)
            using (DmConnection conn = new DmConnection(connectionString))
                conn.Open();
                using (DbTransaction trans = conn.BeginTransaction())
                    using (DmCommand cmd = new DmCommand())
                    {
                        cmd.Connection = conn;
                        cmd.Transaction = trans;
                        try
                        {
                            for (int n = 0; n < sqlList.Count; n++)
                            {
                                string sql = sqlList[n].ToString();
                                if (sql.Trim().Length > 1)
                                {
                                    cmd.CommandText = sql;
                                    cmd.ExecuteNonQuery();
                                }
                            }
                            trans.Commit();
                        }
                        catch (DmException ex)
                            trans.Rollback();
                            throw ex;
                    }
        public async Task ExecuteSqlTransAsync(ArrayList sqlList)
                await conn.OpenAsync();
                using (DbTransaction trans = await conn.BeginTransactionAsync())
                                    await cmd.ExecuteNonQueryAsync();
        /// 执行一条SQL查询语句,返回查询结果。
        /// <returns>查询结果</returns>
        public object GetSingle(string sql)
                    object obj = cmd.ExecuteScalar();
                    if ((object.Equals(obj, null)) || (object.Equals(obj, DBNull.Value)))
                        return null;
                    else
                        return obj;
        public async Task<object> GetSingleAsync(string sql)
                    object obj = await cmd.ExecuteScalarAsync();
        /// 执行查询语句,返回DbDataReader(切记要手工关闭DbDataReader)
        /// <param name="sql">查询语句</param>
        /// <returns>DmDataReader</returns>
        public DbDataReader ExecuteReader(string sql)
            DmConnection connection = new DmConnection(connectionString);
            DmCommand cmd = new DmCommand(sql, connection);
            connection.Open();
            return cmd.ExecuteReader();
        public async Task<DbDataReader> ExecuteReaderAsync(string sql)
            await connection.OpenAsync();
            return await cmd.ExecuteReaderAsync();
        /// 执行查询语句,返回DataSet
        /// <returns>DataSet</returns>
        public DataSet Query(string sql)
                using (DmDataAdapter command = new DmDataAdapter(sql, connection))
                    DataSet ds = new DataSet();
                    command.Fill(ds, "ds");
                    return ds;
        /// 执行查询语句,返回DataSet(可自定义超时时间)
        /// <param name="sql"></param>
        /// <param name="timeout"></param>
        public DataSet Query(string sql, int timeout)
                    command.SelectCommand.CommandTimeout = timeout;
        #endregion 执行简单SQL语句
        #region 执行带参数的SQL语句
        public int ExecuteSql(string sql, params DmParameter[] paras)
                using (DmCommand cmd = new DmCommand())
                    PrepareCommand(cmd, connection, null, sql, paras);
                    cmd.Parameters.Clear();
        public async Task<int> ExecuteSqlAsync(string sql, params DmParameter[] paras)
                    await PrepareCommandAsync(cmd, connection, null, sql, paras);
        /// 执行添加SQL语句,返回记录的ID(自动产生的自增主键)
        /// <param name="parms">SQL参数</param>
        /// <returns>记录的ID</returns>
        public int ExecuteAdd(string sql, params DmParameter[] parms)
            sql = sql + ";Select @@IDENTITY";
                    PrepareCommand(cmd, connection, null, sql, parms);
                    int recordID = Int32.Parse(cmd.ExecuteScalar().ToString());
                    return recordID;
        public async Task<int> ExecuteAddAsync(string sql, params DmParameter[] parms)
            sql = sql + ";select @@identity as newautoid";
                    await PrepareCommandAsync(cmd, connection, null, sql, parms);
                    int recordID;
                    try
                        recordID = int.Parse((await cmd.ExecuteScalarAsync()).ToString());
                    catch
                        recordID = -1;
        /// <param name="sqlList">SQL语句的哈希表(key为sql语句,value是该语句的DmParameter[])</param>
        public void ExecuteSqlTrans(Hashtable sqlList)
                            foreach (DictionaryEntry entry in sqlList)
                                var sql = entry.Key.ToString();
                                var paras = (DmParameter[])entry.Value;
                                PrepareCommand(cmd, conn, trans, sql, paras);
                                int val = cmd.ExecuteNonQuery();
                                cmd.Parameters.Clear();
        public async Task ExecuteSqlTransAsync(Hashtable sqlList)
                                await PrepareCommandAsync(cmd, conn, trans, sql, paras);
                                int val = await cmd.ExecuteNonQueryAsync();
        /// 执行一条计算查询结果语句,返回查询结果。
        public object GetSingle(string sql, params DmParameter[] parms)
                    PrepareCommand(cmd, conn, null, sql, parms);
        public async Task<object> GetSingleAsync(string sql, params DmParameter[] parms)
                    await PrepareCommandAsync(cmd, conn, null, sql, parms);
        /// 执行查询语句,返回DmDataReader (切记要手工关闭DmDataReader)
        public DbDataReader ExecuteReader(string sql, params DmParameter[] parms)
            DmCommand cmd = new DmCommand();
            PrepareCommand(cmd, connection, null, sql, parms);
            DbDataReader myReader = cmd.ExecuteReader();
            cmd.Parameters.Clear();
            return myReader;
        public async Task<DbDataReader> ExecuteReaderAsync(string sql, params DmParameter[] parms)
            await PrepareCommandAsync(cmd, connection, null, sql, parms);
            var myReader = await cmd.ExecuteReaderAsync();
        /// <param name="paras">参数数组</param>
        public DataSet Query(string sql, params DmParameter[] paras)
                    using (DmDataAdapter da = new DmDataAdapter(cmd))
                        da.Fill(ds, "ds");
                        cmd.Parameters.Clear();
                        return ds;
        /// 准备SQL查询命令
        /// <param name="cmd">SQL命令对象</param>
        /// <param name="conn">SQL连接对象</param>
        /// <param name="trans">SQL事务对象</param>
        /// <param name="cmdText">SQL语句</param>
        private void PrepareCommand(DmCommand cmd, DmConnection conn, DbTransaction trans, string cmdText, DmParameter[] paras)
            if (conn.State != ConnectionState.Open)
            cmd.Connection = conn;
            cmd.CommandText = cmdText;
            if (trans != null)
                cmd.Transaction = trans;
            cmd.CommandType = CommandType.Text;
            if (paras != null)
                foreach (DmParameter parameter in paras)
                    if ((parameter.Direction == ParameterDirection.InputOutput || parameter.Direction == ParameterDirection.Input) &&
                        (parameter.Value == null))
                        parameter.Value = DBNull.Value;
                    cmd.Parameters.Add(parameter);
        private async Task PrepareCommandAsync(DmCommand cmd, DmConnection conn, DbTransaction trans, string cmdText, DmParameter[] paras)
        #endregion 执行带参数的SQL语句
    }

使用方法也很简单,传入SQL语句和参数即可。这里给出几个增删改查的例子:

 public class PersonAdoNetDAL : IPersonDAL
    {
        static readonly DmDbClient _client = new DmDbClient("Server=127.0.0.1; UserId=TESTDB; PWD=1234567");

        public int Add(PersonModel model)
        {
            string sql = "insert into Person(Name,City) Values(:Name,:City)";
            DmParameter[] paras = new DmParameter[] {
                new DmParameter(":Name",model.Name),
                new DmParameter(":City",model.City)
            };
            return _client.ExecuteAdd(sql, paras);
        }
        public bool Update(PersonModel model)
            string sql = "update Person set City=:City where Id=:Id";
                new DmParameter(":Id",model.Id),
            return _client.ExecuteSql(sql, paras) > 0 ? true : false;
        public bool Delete(int id)
            string sql = "delete from Person where Id=:Id";
                new DmParameter(":Id",id),
        public PersonModel Get(int id)
            string sql = "select Id,Name,City from Person where Id=:Id";
            PersonModel model = null;
            using (var reader = (DmDataReader)_client.ExecuteReader(sql, paras))
            {
                while (reader.Read())
                {
                    model = new PersonModel();
                    model.Id = reader.GetInt32(0);
                    model.Name = reader.GetString(1);
                    model.City = reader.GetString(2);
                }
            }
            return model;
        public List<PersonModel> GetList()
            var list = new List<PersonModel>();
            using (var reader = (DmDataReader)_client.ExecuteReader("select Id,Name,City from Person"))
                    var model = new PersonModel();
                    list.Add(model);
            return list;
    }

需要注意达梦数据库的参数是用冒号作为前缀的。另外数据表和字段的名字建议全部使用大写字母,单词之间使用下划线分隔,也就是蛇形命名法。此时SQL语句就不用关心大小写了,怎么写都行。

Dapper方式

Dapper是一个轻量级的ORM框架,现在使用的也很广泛,可以简化代码编写。因为Dapper扩展的IDbConnection,这是ADO.NET中的东西,我们使用的DmProvider也是实现了ADO.NET相关接口,所以Dapper可以通过DmProvider操作达梦数据库。

首先定义一个获取数据库连接对象的工厂类:

 public class DmConnectionFactory
    {
        static string sqlConnString = "Server=127.0.0.1; UserId=TESTDB; PWD=123456";
        public static IDbConnection GetConn()
        {
            return new DmConnection(sqlConnString);
        }
    }

然后就可以使用它执行SQL语句了:

 public class PersonDapperDAL : IPersonDAL
    {
        public PersonDapperDAL()
        {
        }
        public PersonModel Get(int id)
        {
            string sql = "select Id,Name,City from Person where Id=:Id";
            return DmConnectionFactory.GetConn().QueryFirstOrDefault<PersonModel>(sql, new { Id = id });
        }
        public List<PersonModel> GetList()
        {
            string sql = "select Id,Name,City from Person";
            return DmConnectionFactory.GetConn().Query<PersonModel>(sql).ToList();
        }
        public int Add(PersonModel model)
        {
            string sql = "insert into Person(Name,City) Values(:Name,:City);Select @@IDENTITY";
            return DmConnectionFactory.GetConn().QuerySingle<int>(sql, model);
        }
        public bool Update(PersonModel model)
        {
            string sql = "update Person set City=:City where Id=:Id";
            int result = DmConnectionFactory.GetConn().Execute(sql, model);
            return result > 0;
        }
        public bool Delete(int id)
        {
            string sql = "delete from Person where Id=:Id";
            int result = DmConnectionFactory.GetConn().Execute(sql, new { Id = id });
            return result > 0;
        }
    }

Query、Execute这些方法都是Dapper定义的,可以看到能够少写很多代码。这里也不用打开连接、关闭连接,也不用写using,因为Dapper的这些方法中已经做了相关处理。

到此这篇关于国产化之 .NET Core 操作达梦数据库DM8的两种方式的文章就介绍到这了,更多相关.NET Core 达梦数据库DM8内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 为什么ASP.NET Core 数据库连接串的值和appsettings.json配的不一样?

    目录 一.配置读取顺序 二.分析 三.演示 1.读取Providers 2.读取配置值 一.配置读取顺序 ASP.NET Core 中的配置是使用一个或多个配置提供程序执行的,配置提供程序使用各种配置源从键值对读取配置数据. ASP.NET Core 提供了大量可用的配置提供程序,这还不包括可以自定义配置提供程序. 添加配置提供程序的顺序很重要,因为后面的提供程序添加的配置值将覆盖前面的提供程序添加的值. 配置提供程序的典型顺序为: appsettings.json appsettings.En

  • ASP.NET Core基于现有数据库创建EF模型

    1.简介 Entity Framework Core可通过数据库提供给应用程序的插件访问许多不同的数据库.我们可以通过使用Entity Framework Core构建执行基本数据访问的ASP.NET Core MVC应用程序,对现有数据库进行反向工程以便创建Entity Framework模型. 2.创建数据库 我们可以通过Visual Studio创建一个数据库再进行演示,步骤如下:●打开Visual Studio开发工具●“工具”>“连接到数据库”●选择“Microsoft SQL Ser

  • ASP.NET Core使用EF为关系数据库建模

    目录 1.简介 2.表映射 2.1约定 2.2数据注释 2.3Fluent API 3.列映射 3.1约定 3.2数据注释 3.3Fluent API 4.数据类型 4.1约定 4.2数据注释 4.3Fluent API 5.主键 5.1约定 5.2数据注释 5.3Fluent API 6.默认架构 6.1约定 6.2数据注释 6.3Fluent API 7.默认值 7.1约定 7.2数据注释 7.3Fluent API 8.索引(关系数据库) 8.1约定 8.2数据注释 8.3Fluent A

  • 国产化中的 .NET Core 操作达梦数据库DM8的两种方式(操作详解)

    目录 背景 环境 SDK 操作数据库 DbHelperSQL方式 Dapper方式 背景 某个项目需要实现基础软件全部国产化,其中操作系统指定银河麒麟,数据库使用达梦V8,CPU平台的范围包括x64.龙芯.飞腾.鲲鹏等.考虑到这些基础产品对.NET的支持,最终选择了.NET Core 3.1. 环境 CPU平台:x86-64 / Arm64 操作系统:银河麒麟 v4 数据库:DM8 .NET:.NET Core 3.1 SDK 达梦自己提供了.NET操作其数据库的SDK,可以通过NuGet安装,

  • vue3中的对象时为proxy对象如何获取值(两种方式)

    目录 第一种获取target值的方式: 第二种获取target值 PS:vue3中获取proxy包裹的数据 前言 一.具体问题 二.解决办法 使用vue3.0时,因为底层是使用proxy进行代理的所以当我们打印一些值得时候是proxy代理之后的是Proxy对象,Proxy对象里边的[[Target]]才是真实的对象. 第一种获取target值的方式: 通过vue中的响应式对象可使用 toRaw() 方法获取原始对象 //第一种获取target值的方式,通过vue中的响应式对象可使用toRaw()

  • c++中的两种getline用法详解

    getline是C++标准库函数:但不是C标准库函数,而是POSIX(IEEE Std 1003.1-2008版本及以上)所定义的标准库函数(在POSIX IEEE Std 1003.1-2008标准出来之前,则只是GNU扩展库里的函数).getline会生成一个包含一串从输入流读入的字符的字符串,直到以下情况发生会导致生成的此字符串结束:1)到文件结束,2)遇到函数的定界符,3)输入达到最大限度. getline()函数是一个比较常见的函数.根据名字直接"望文->生义",就知道

  • Python代码中引用已经写好的模块、方法的两种方式

    平时写的一些 Python 的代码,需要在其他模块里面复用.最粗狂的方法就是直接 copy 过去. 但这种方式太麻烦,copy 一堆代码,导致代码量也很多.copy 的也不爽. 下面就介绍两种方式,可以简洁明了地调用自己在其他模块写的代码. 个人推荐第二种方式. 方式一: 手动使用 sys 调用自己写的 Python 模块.方法 我的代码存在 E:\\PycharmProjects\\111 目录下.需要调用的代码是 mypy 下 my007.py 里的 funA() 方法. my007.py

  • asp.net操作javascript:confirm返回值的两种方式

    在asp.net中使用confirm可以分为两种: 1.没有使用ajax,confirm会引起也面刷新 2.使用了ajax,不会刷新 A.没有使用ajax,可以用StringBuilder来完成. (一)asp.net用StringBuilder控制后台操作javascript:confirm返回值,此方法比较烦琐 1.后台启动事件 StringBuilder sb = new StringBuilder(); sb.Append("<script language='javascript

  • Java中分割字符串的两种方法实例详解

    前言 相信大家应该都知道在java编程中,有时候我们需要把一个字符串按照某个特定字符.字母等作为截点分割这个字符串,这样我们就可以使用这个字符串的一部分或者把所有截取的内容保存到数组里等操作.下面这篇文章就给大家分享了两种分割的方法,下面来一起看看吧. 一.java.lang.String 的 split() 方法, JDK 1.4 or later public String[] split(String regex,int limit) 示例代码 public class StringSpl

  • java关于并发模型中的两种锁知识点详解

    1.悲观锁 悲观锁假设最坏的情况(如果果你不锁门,那么捣蛋鬼就会闯入并搞得一团糟),只有在确保其他线程不受干扰(获得正确的锁)的情况下才能执行. 一般实现如独占锁等. 安全性更高,但中低并发性效率更低. 2.乐观锁 乐观锁通过冲突检查机制判断更新过程中是否存在其他线程干扰.如果存在,操作将失败,重试(也可以不重试). CAS等常见实现. 一些乐观锁削弱了一致性,但在中低并发性下效率大大提高. 知识点扩展: 并行与分布式编程 关注的是复杂软件系统的构造,"复杂"是指多线程.分布式与GUI

  • asp.core 同时兼容JWT身份验证和Cookies 身份验证两种模式(示例详解)

    在实际使用中,可能会遇到,aspi接口验证和view页面的登录验证情况.asp.core 同样支持两种兼容. 首先在startup.cs 启用身份验证. var secrityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"])); services.AddSingleton(secrityKey); services.AddAuthentication(CookieAut

  • C语言中栈的两种实现方法详解

    目录 一.顺序栈 二.链式栈 总结 一.顺序栈 #include<stdio.h> #include<stdlib.h> #define maxsize 64 //定义栈 typedef struct { int data[maxsize]; int top; }sqstack,*sqslink; //设置栈空 void Clearstack(sqslink s) { s->top=-1; } //判断栈空 int Emptystack(sqslink s) { if (s-

  • Centos7 安装达梦数据库的教程

    1 准备工作 安装好Linux操作系统这里选择的是Linux 7: [root@slave1 software]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) 关闭防火墙 和 Selinux: [root@slave1 software]# systemctl stop firewalld [root@slave1 software]# systemctl disable firewalld [root@slave1

随机推荐