c#几种数据库的大数据批量插入(SqlServer、Oracle、SQLite和MySql)

7 篇文章 0 订阅

转自:https://www.zhangshengrong.com/p/OgN5BjdXnW/
https://www.cnblogs.com/faib/archive/2012/04/18/2456001.html
一帆数据库操作

c#几种数据库的大数据批量插入(SqlServer、Oracle、SQLite和MySql)

在之前只知道SqlServer支持数据批量插入,殊不知道Oracle、SQLite和MySql也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解决方法。

首先说一下,IProvider里有一个用于实现批量插入的插件服务接口IBatcherProvider,此接口在前一篇文章中已经提到过了。

    /// <summary>
      /// 提供数据批量处理的方法。
      /// </summary>
      public interface IBatcherProvider : IProviderService
      {
        /// <summary>
        /// 将 <see cref="DataTable"/> 的数据批量插入到数据库中。
        /// </summary>
        /// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>
        /// <param name="batchSize">每批次写入的数据量。</param>
        void Insert(DataTable dataTable, int batchSize = 10000);
      }

一、SqlServer数据批量插入

SqlServer的批量插入很简单,使用SqlBulkCopy就可以,以下是该类的实现:

    /// <summary>
      /// 为 System.Data.SqlClient 提供的用于批量操作的方法。
      /// </summary>
      public sealed class MsSqlBatcher : IBatcherProvider
      {
        /// <summary>
        /// 获取或设置提供者服务的上下文。
        /// </summary>
        public ServiceContext ServiceContext { get; set; }
     
        /// <summary>
        /// 将 <see cref="DataTable"/> 的数据批量插入到数据库中。
        /// </summary>
        /// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>
        /// <param name="batchSize">每批次写入的数据量。</param>
        public void Insert(DataTable dataTable, int batchSize = 10000)
        {
          Checker.ArgumentNull(dataTable, "dataTable");
          if (dataTable.Rows.Count == 0)
          {
            return;
          }
          using (var connection = (SqlConnection)ServiceContext.Database.CreateConnection())
          {
            try
            {
              connection.TryOpen();
              //给表名加上前后导符
              var tableName = DbUtility.FormatByQuote(ServiceContext.Database.Provider.GetService<ISyntaxProvider>(), dataTable.TableName);
              using (var bulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, null)
                {
                  DestinationTableName = tableName,
                  BatchSize = batchSize
                })
              {
                //循环所有列,为bulk添加映射
                dataTable.EachColumn(c => bulk.ColumnMappings.Add(c.ColumnName, c.ColumnName), c => !c.AutoIncrement);
                bulk.WriteToServer(dataTable);
                bulk.Close();
              }
            }
            catch (Exception exp)
            {
              throw new BatcherException(exp);
            }
            finally
            {
              connection.TryClose();
            }
          }
        }
      }

以上没有使用事务,使用事务在性能上会有一定的影响,如果要使用事务,可以设置SqlBulkCopyOptions.UseInternalTransaction。

二、Oracle数据批量插入

System.Data.OracleClient不支持批量插入,因此只能使用Oracle.DataAccess组件来作为提供者。

    /// <summary>
      /// Oracle.Data.Access 组件提供的用于批量操作的方法。
      /// </summary>
      public sealed class OracleAccessBatcher : IBatcherProvider
      {
        /// <summary>
        /// 获取或设置提供者服务的上下文。
        /// </summary>
        public ServiceContext ServiceContext { get; set; }
     
        /// <summary>
        /// 将 <see cref="DataTable"/> 的数据批量插入到数据库中。
        /// </summary>
        /// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>
        /// <param name="batchSize">每批次写入的数据量。</param>
        public void Insert(DataTable dataTable, int batchSize = 10000)
        {
          Checker.ArgumentNull(dataTable, "dataTable");
          if (dataTable.Rows.Count == 0)
          {
            return;
          }
          using (var connection = ServiceContext.Database.CreateConnection())
          {
            try
            {
              connection.TryOpen();
              using (var command = ServiceContext.Database.Provider.DbProviderFactory.CreateCommand())
              {
                if (command == null)
                {
                  throw new BatcherException(new ArgumentException("command"));
                }
                command.Connection = connection;
                command.CommandText = GenerateInserSql(ServiceContext.Database, command, dataTable);
                command.ExecuteNonQuery();
              }
            }
            catch (Exception exp)
            {
              throw new BatcherException(exp);
            }
            finally
            {
              connection.TryClose();
            }
          }
        }
     
        /// <summary>
        /// 生成插入数据的sql语句。
        /// </summary>
        /// <param name="database"></param>
        /// <param name="command"></param>
        /// <param name="table"></param>
        /// <returns></returns>
        private string GenerateInserSql(IDatabase database, DbCommand command, DataTable table)
        {
          var names = new StringBuilder();
          var values = new StringBuilder();
          //将一个DataTable的数据转换为数组的数组
          var data = table.ToArray();
     
          //设置ArrayBindCount属性
          command.GetType().GetProperty("ArrayBindCount").SetValue(command, table.Rows.Count, null);
     
          var syntax = database.Provider.GetService<ISyntaxProvider>();
          for (var i = 0; i < table.Columns.Count; i++)
          {
            var column = table.Columns[i];
     
            var parameter = database.Provider.DbProviderFactory.CreateParameter();
            if (parameter == null)
            {
              continue;
            }
            parameter.ParameterName = column.ColumnName;
            parameter.Direction = ParameterDirection.Input;
            parameter.DbType = column.DataType.GetDbType();
            parameter.Value = data[i];
     
            if (names.Length > 0)
            {
              names.Append(",");
              values.Append(",");
            }
            names.AppendFormat("{0}", DbUtility.FormatByQuote(syntax, column.ColumnName));
            values.AppendFormat("{0}{1}", syntax.ParameterPrefix, column.ColumnName);
     
            command.Parameters.Add(parameter);
          }
          return string.Format("INSERT INTO {0}({1}) VALUES ({2})", DbUtility.FormatByQuote(syntax, table.TableName), names, values);
        }
      }

以上最重要的一步,就是将DataTable转为数组的数组表示,即object[][],前数组的上标是列的个数,后数组是行的个数,因此循环Columns将后数组作为Parameter的值,也就是说,参数的值是一个数组。而insert语句与一般的插入语句没有什么不一样。

三、SQLite数据批量插入

SQLite的批量插入只需开启事务就可以了,这个具体的原理不得而知。第六章中有对Sqlite批量插入的内容补充。

    public sealed class SQLiteBatcher : IBatcherProvider
      {
        /// <summary>
        /// 获取或设置提供者服务的上下文。
        /// </summary>
        public ServiceContext ServiceContext { get; set; }
     
        /// <summary>
        /// 将 <see cref="DataTable"/> 的数据批量插入到数据库中。
        /// </summary>
        /// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>
        /// <param name="batchSize">每批次写入的数据量。</param>
        public void Insert(DataTable dataTable, int batchSize = 10000)
        {
          Checker.ArgumentNull(dataTable, "dataTable");
          if (dataTable.Rows.Count == 0)
          {
            return;
          }
          using (var connection = ServiceContext.Database.CreateConnection())
          {
            DbTransaction transcation = null;
            try
            {
              connection.TryOpen();
              transcation = connection.BeginTransaction();
              using (var command = ServiceContext.Database.Provider.DbProviderFactory.CreateCommand())
              {
                if (command == null)
                {
                  throw new BatcherException(new ArgumentException("command"));
                }
                command.Connection = connection;
     
                command.CommandText = GenerateInserSql(ServiceContext.Database, dataTable);
                if (command.CommandText == string.Empty)
                {
                  return;
                }
     
                var flag = new AssertFlag();
                dataTable.EachRow(row =>
                  {
                    var first = flag.AssertTrue();
                    ProcessCommandParameters(dataTable, command, row, first);
                    command.ExecuteNonQuery();
                  });
              }
              transcation.Commit();
            }
            catch (Exception exp)
            {
              if (transcation != null)
              {
                transcation.Rollback();
              }
              throw new BatcherException(exp);
            }
            finally
            {
              connection.TryClose();
            }
          }
        }
     
        private void ProcessCommandParameters(DataTable dataTable, DbCommand command, DataRow row, bool first)
        {
          for (var c = 0; c < dataTable.Columns.Count; c++)
          {
            DbParameter parameter;
            //首次创建参数,是为了使用缓存
            if (first)
            {
              parameter = ServiceContext.Database.Provider.DbProviderFactory.CreateParameter();
              parameter.ParameterName = dataTable.Columns[c].ColumnName;
              command.Parameters.Add(parameter);
            }
            else
            {
              parameter = command.Parameters[c];
            }
            parameter.Value = row[c];
          }
        }
     
        /// <summary>
        /// 生成插入数据的sql语句。
        /// </summary>
        /// <param name="database"></param>
        /// <param name="table"></param>
        /// <returns></returns>
        private string GenerateInserSql(IDatabase database, DataTable table)
        {
          var syntax = database.Provider.GetService<ISyntaxProvider>();
          var names = new StringBuilder();
          var values = new StringBuilder();
          var flag = new AssertFlag();
          table.EachColumn(column =>
            {
              if (!flag.AssertTrue())
              {
                names.Append(",");
                values.Append(",");
              }
              names.Append(DbUtility.FormatByQuote(syntax, column.ColumnName));
              values.AppendFormat("{0}{1}", syntax.ParameterPrefix, column.ColumnName);
            });
          return string.Format("INSERT INTO {0}({1}) VALUES ({2})", DbUtility.FormatByQuote(syntax, table.TableName), names, values);
        }
      }

四、MySql数据批量插入

    /// <summary>
      /// 为 MySql.Data 组件提供的用于批量操作的方法。
      /// </summary>
      public sealed class MySqlBatcher : IBatcherProvider
      {
        /// <summary>
        /// 获取或设置提供者服务的上下文。
        /// </summary>
        public ServiceContext ServiceContext { get; set; }
     
        /// <summary>
        /// 将 <see cref="DataTable"/> 的数据批量插入到数据库中。
        /// </summary>
        /// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>
        /// <param name="batchSize">每批次写入的数据量。</param>
        public void Insert(DataTable dataTable, int batchSize = 10000)
        {
          Checker.ArgumentNull(dataTable, "dataTable");
          if (dataTable.Rows.Count == 0)
          {
            return;
          }
          using (var connection = ServiceContext.Database.CreateConnection())
          {
            try
            {
              connection.TryOpen();
              using (var command = ServiceContext.Database.Provider.DbProviderFactory.CreateCommand())
              {
                if (command == null)
                {
                  throw new BatcherException(new ArgumentException("command"));
                }
                command.Connection = connection;
     
                command.CommandText = GenerateInserSql(ServiceContext.Database, command, dataTable);
                if (command.CommandText == string.Empty)
                {
                  return;
                }
                command.ExecuteNonQuery();
              }
            }
            catch (Exception exp)
            {
              throw new BatcherException(exp);
            }
            finally
            {
              connection.TryClose();
            }
          }
        }
     
        /// <summary>
        /// 生成插入数据的sql语句。
        /// </summary>
        /// <param name="database"></param>
        /// <param name="command"></param>
        /// <param name="table"></param>
        /// <returns></returns>
        private string GenerateInserSql(IDatabase database, DbCommand command, DataTable table)
        {
          var names = new StringBuilder();
          var values = new StringBuilder();
          var types = new List<DbType>();
          var count = table.Columns.Count;
          var syntax = database.Provider.GetService<ISyntaxProvider>();
          table.EachColumn(c =>
            {
              if (names.Length > 0)
              {
                names.Append(",");
              }
              names.AppendFormat("{0}", DbUtility.FormatByQuote(syntax, c.ColumnName));
              types.Add(c.DataType.GetDbType());
            });
     
          var i = 0;
          foreach (DataRow row in table.Rows)
          {
            if (i > 0)
            {
              values.Append(",");
            }
            values.Append("(");
            for (var j = 0; j < count; j++)
            {
              if (j > 0)
              {
                values.Append(", ");
              }
              var isStrType = IsStringType(types[j]);
              var parameter = CreateParameter(database.Provider, isStrType, types[j], row[j], syntax.ParameterPrefix, i, j);
              if (parameter != null)
              {
                values.Append(parameter.ParameterName);
                command.Parameters.Add(parameter);
              }
              else if (isStrType)
              {
                values.AppendFormat("'{0}'", row[j]);
              }
              else
              {
                values.Append(row[j]);
              }
            }
            values.Append(")");
            i++;
          }
          return string.Format("INSERT INTO {0}({1}) VALUES {2}", DbUtility.FormatByQuote(syntax, table.TableName), names, values);
        }
     
        /// <summary>
        /// 判断是否为字符串类别。
        /// </summary>
        /// <param name="dbType"></param>
        /// <returns></returns>
        private bool IsStringType(DbType dbType)
        {
          return dbType == DbType.AnsiString || dbType == DbType.AnsiStringFixedLength || dbType == DbType.String || dbType == DbType.StringFixedLength;
        }
     
        /// <summary>
        /// 创建参数。
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="isStrType"></param>
        /// <param name="dbType"></param>
        /// <param name="value"></param>
        /// <param name="parPrefix"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <returns></returns>
        private DbParameter CreateParameter(IProvider provider, bool isStrType, DbType dbType, object value, char parPrefix, int row, int col)
        {
          //如果生成全部的参数,则速度会很慢,因此,只有数据类型为字符串(包含'号)和日期型时才添加参数
          if ((isStrType && value.ToString().IndexOf('\'') != -1) || dbType == DbType.DateTime)
          {
            var name = string.Format("{0}p_{1}_{2}", parPrefix, row, col);
            var parameter = provider.DbProviderFactory.CreateParameter();
            parameter.ParameterName = name;
            parameter.Direction = ParameterDirection.Input;
            parameter.DbType = dbType;
            parameter.Value = value;
            return parameter;
          }
          return null;
        }
      }

MySql的批量插入,是将值全部写在语句的values里,例如,insert batcher(id, name) values(1, ‘1’, 2, ‘2’, 3, ‘3’, … 10, ‘10’)。

五、测试

接下来写一个测试用例来看一下使用批量插入的效果。

     public void TestBatchInsert()
        {
          Console.WriteLine(TimeWatcher.Watch(() =>
            InvokeTest(database =>
              {
                var table = new DataTable("Batcher");
                table.Columns.Add("Id", typeof(int));
                table.Columns.Add("Name1", typeof(string));
                table.Columns.Add("Name2", typeof(string));
                table.Columns.Add("Name3", typeof(string));
                table.Columns.Add("Name4", typeof(string));
     
                //构造100000条数据
                for (var i = 0; i < 100000; i++)
                {
                  table.Rows.Add(i, i.ToString(), i.ToString(), i.ToString(), i.ToString());
                }
     
                //获取 IBatcherProvider
                var batcher = database.Provider.GetService<IBatcherProvider>();
                if (batcher == null)
                {
                  Console.WriteLine("不支持批量插入。");
                }
                else
                {
                  batcher.Insert(table);
                }
     
                //输出batcher表的数据量
                var sql = new SqlCommand("SELECT COUNT(1) FROM Batcher");
                Console.WriteLine("当前共有 {0} 条数据", database.ExecuteScalar(sql));
     
              })));
        }

以下表中列出了四种数据库生成10万条数据各耗用的时间

数据库耗用时间
MsSql00:00:02.9376300
Oracle00:00:01.5155959
SQLite00:00:01.6275634
MySql00:00:05.4166891

时间: 2016-11-08

六、补充

SQLite批量插入使用到的接口介绍
Fireasy.Data的一个主要接口是IDatabase,这个与网上流传的SqlHelper差不多是完成一样的操作。不过,在IDatabase中只提供了几个高内聚的方法,你不必去传递那些DbCommand和DbParameter。不同的数据库类型,都提供实现IProvider接口的类,来指定DbProviderFactory,以及各种的IProviderService组合来实现更多的功能。
下面先来看一下有关IDatabase及周围的一些接口组合:
在这里插入图片描述 1、IDatabase接口
在Fireasy.Data中,IDatabase是最底层的接口,它提供了以下几个属性和方法:
ConnectionString:数据库的连接字符串对象。
Provider:为IDatabase提供的不同数据库的实现,也是一个重要的接口,这个将在后面进行介绍。
BeginTransaction:开始数据库事务,加上了事务锁,如果IDatabase之前已经开始了事务,再将调用该方法是将返回false。
CommitTransaction:提交数据库事务,如果是与BeginTransaction方法匹配的,则可以提交,否则返回false。
RollbackTransaction:回滚数据库事务,如果是与BeginTransaction方法匹配的,则可以回滚,否则返回false。
ExecuteDataTable:执行一个查询语句,将结果以DataTable返回。
ExecuteEnumerable:执行一个查询语句,将结果以T序列返回,可以指定你的IDataRowMapper来进行转换,默认是使用DefaultRowMapper。
ExecuteNonQuery:执行一个查询语句,返回影响的行数。
ExecuteReader:执行一个查询语句,以IDataReader返回结果。
ExecuteScalar:执行一个查询语句,返回第一行的第一列。
FillDataSet:执行一个查询语句,将结果填充到DataSet。
Update:将一个DataTable的改动保存到数据库。

2、IProvider接口
IProvider针对不同的数据库类型,提供其实现类,它的一个主要属性是DbProviderFactory。一般数据库的驱动都基于Ado.Net,因此它们就必须提供自己的DbProviderFactory。DbProviderFactory用于创建DbConnection、DbCommand、DbParameter等实例。
另外,IProvider还提供了一组方法,方便将一些扩展的接口以插件的方式注入到Provider中。目前提供的插件服务接口有IBackupProvider、IBatcherProvider、ISyntaxProvider、IGeneratorProvider、ISchemaProvider、ICommandWatcher和ITranslateProvider。
RegisterService:注册一个插件服务实例。这些实例必须是实现IProviderService接口。
GetServices:获取所有的已注册的插件实例。
GetService:获取指定类型的插件服务实例。

3、IBackupProvider接口
该接口为数据库提供者提供数据库的备份与恢复操作,目前只是一个雏形,只有MsSql实现了该接口。
Backup:备份指定的数据库到指定的文件。
Restore:从指定的文件恢复数据库。

4、IBatcherProvider接口
该接口为数据库提供者提供数据的批量插入支持。大部份数据库,如MsSql、MySql、Oracle、SQLite都提供了批量插入数据的方法,因此只要实现该接口方法就可以批量插入数据了。在Fireasy中,已经为四种数据库类型实现了批量插入的方法。以后会逐一介绍。
Insert:将一整个DataTable里的数据一次性或分批写入到数据库。

5、ISyntaxProvider接口
该接口为数据库提供者提供SQL语法解析的支持。众所周知,一个Length函数在不同的数据库中写法都可能不相同,因此ISyntaxProvider提供了对字符串、日期、数学运算三组语法的解析,还有存储参数前缀、字段前导后导符,分页方法、数据类型转换等多种方法。
StringSyntax:字符串函数的解析类,里面的方法不再介绍了。
DateTimeSyntax:日期函数的解析类,里面的方法不再介绍了。
MathSyntax:数学运算函数的解析类,里面的方法不再介绍了。
IdentitySelect:获取最近创建的自动编号的查询文本。
Segment:对Sql语法使用IDataSegment进行分段处理,返回添加了分段语法的后的sql。
Convert:将字段转换为指定的数据类型,如cast(name, nvarchar)。
Column:生成相应类型的数据类型关键字,如MsSql里将DbType.String生成nvarchar。
Coalesce:如果源表达式为 null,则依次判断给定的一组参数,直至某参数非 null 时返回,这个就象是C#里的 var db = str1 ?? str2 ?? str3。

6、ISchemaProvider接口
该接口为数据库提供者提供数据库架构的查询,可以返回如表、字段这些信息的元数据。
GetSchemas:获取指定T类型的架构信息,T是实现自ISchemaMetadata,如Table、Column、Procedure等。可以使用表达式对架构进行查询,如GetSchemas

(s => s.TableName == “Product”)。
GetSchemas:这个与DbConnection里的方法一样,返回一个DataTable。

7、ICommandWatcher接口
该接口应该与数据库提供者无关,它只是切入IDatabase内部,在执行Sql的时候使用该接口进行外部通知。
Notify:通知外部程序,所执行的Sql以及耗用的时间。

8、ITranslateProvider接口
该接口为数据库提供者提供实体Linq查询的解析,你可以书写一些Linq查询,然后交给该接口进行解析,最终得到数据库能够执行的Sql。考虑到这部份的复杂性,将单独开几篇文章进行介绍。
Fireasy.Data最底层的接口主要就是围绕IDatabase和IProvider组织的,如果以后需要对IDatabase的功能进行扩充,我们只需要定义一个新的接口继承自IProviderService,然后在相应的Provider内进行注册,当然还提供了Provider的配置,可以方便的进行组合。
Fireasy.Data底层的介绍就是这些,不知道你对Fireasy.Data有没有一个大概的认识了,不妨了说说你的想法。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一个基本的DBhelper类,它可以连接到Oracle、SQL Server、MySQLSQLite数据库,并实现常见的增删改查功能、事务和存储过程的执行。以下是示例代码: ```csharp using System; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Data.SQLite; using System.Data.OracleClient; using MySql.Data.MySqlClient; public class DBHelper { private string connectionString; // 数据库连接字符串 private DbProviderFactory factory; // 数据库工厂对象 public DBHelper(string dbType, string connStr) { connectionString = connStr; // 根据数据库类型创建对应的数据库工厂对象 switch (dbType.ToLower()) { case "oracle": factory = DbProviderFactories.GetFactory("System.Data.OracleClient"); break; case "sqlserver": factory = DbProviderFactories.GetFactory("System.Data.SqlClient"); break; case "mysql": factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient"); break; case "sqlite": factory = DbProviderFactories.GetFactory("System.Data.SQLite"); break; default: throw new Exception("不支持的数据库类型!"); } } // 执行查询,并返回查询结果的 DataTable 对象 public DataTable ExecuteQuery(string sql, CommandType cmdType, params DbParameter[] parameters) { using (DbConnection conn = factory.CreateConnection()) { conn.ConnectionString = connectionString; conn.Open(); DbCommand cmd = conn.CreateCommand(); cmd.CommandText = sql; cmd.CommandType = cmdType; if (parameters != null && parameters.Length > 0) { cmd.Parameters.AddRange(parameters); } DbDataAdapter adapter = factory.CreateDataAdapter(); adapter.SelectCommand = cmd; DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } // 执行非查询操作,返回受影响的行数 public int ExecuteNonQuery(string sql, CommandType cmdType, params DbParameter[] parameters) { using (DbConnection conn = factory.CreateConnection()) { conn.ConnectionString = connectionString; conn.Open(); DbCommand cmd = conn.CreateCommand(); cmd.CommandText = sql; cmd.CommandType = cmdType; if (parameters != null && parameters.Length > 0) { cmd.Parameters.AddRange(parameters); } int result = cmd.ExecuteNonQuery(); return result; } } // 执行查询,并返回查询结果的第一行第一列的值(Object类型) public object ExecuteScalar(string sql, CommandType cmdType, params DbParameter[] parameters) { using (DbConnection conn = factory.CreateConnection()) { conn.ConnectionString = connectionString; conn.Open(); DbCommand cmd = conn.CreateCommand(); cmd.CommandText = sql; cmd.CommandType = cmdType; if (parameters != null && parameters.Length > 0) { cmd.Parameters.AddRange(parameters); } object result = cmd.ExecuteScalar(); return result; } } // 开始一个事务 public DbTransaction BeginTransaction() { DbConnection conn = factory.CreateConnection(); conn.ConnectionString = connectionString; conn.Open(); DbTransaction trans = conn.BeginTransaction(); return trans; } // 提交一个事务 public void CommitTransaction(DbTransaction trans) { trans.Commit(); trans.Connection.Close(); } // 回滚一个事务 public void RollbackTransaction(DbTransaction trans) { trans.Rollback(); trans.Connection.Close(); } // 执行存储过程 public void ExecuteProcedure(string procName, CommandType cmdType, params DbParameter[] parameters) { using (DbConnection conn = factory.CreateConnection()) { conn.ConnectionString = connectionString; conn.Open(); DbCommand cmd = conn.CreateCommand(); cmd.CommandText = procName; cmd.CommandType = cmdType; if (parameters != null && parameters.Length > 0) { cmd.Parameters.AddRange(parameters); } cmd.ExecuteNonQuery(); } } } ``` 使用示例: ```csharp // 创建一个连接 Oracle 数据库的 DBHelper 对象 DBHelper oracleHelper = new DBHelper("oracle", "Data Source=127.0.0.1:1521/orcl;User ID=scott;Password=tiger;"); // 执行查询,并返回查询结果的 DataTable 对象 DataTable dataTable = oracleHelper.ExecuteQuery("SELECT * FROM emp", CommandType.Text); // 执行非查询操作,返回受影响的行数 int result = oracleHelper.ExecuteNonQuery("UPDATE emp SET sal = sal * 1.1", CommandType.Text); // 执行查询,并返回查询结果的第一行第一列的值(Object类型) object value = oracleHelper.ExecuteScalar("SELECT COUNT(*) FROM emp", CommandType.Text); // 开始一个事务 DbTransaction trans = oracleHelper.BeginTransaction(); try { // 执行一些操作 // 提交事务 oracleHelper.CommitTransaction(trans); } catch (Exception ex) { // 回滚事务 oracleHelper.RollbackTransaction(trans); } // 执行存储过程 DbParameter[] parameters = new DbParameter[] { new OracleParameter("inParam", "value"), new OracleParameter("outParam", OracleType.VarChar, 50, ParameterDirection.Output, false, 0, 0, "", DataRowVersion.Default, null) }; oracleHelper.ExecuteProcedure("procName", CommandType.StoredProcedure, parameters); ``` 以上是一个简单的DBhelper类,您可以根据自己的需求进行扩展和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值