本文将带您了解关于如何开发支持oracle和mssql双版本数据库的产品的新内容,同时我们还将为您解释oracle数据库开发工具的相关知识,另外,我们还将为您提供关于Bool支持OracleSQL、C
本文将带您了解关于如何开发支持oracle和mssql双版本数据库的产品的新内容,同时我们还将为您解释oracle数据库开发工具的相关知识,另外,我们还将为您提供关于Bool支持Oracle SQL、C# 多数据库组件包,支持 MSSQL+Oracle+MySQL + 用户操作手册 | C/S 开发框架、c#几种数据库的大数据批量插入(SqlServer、Oracle、SQLite和MySql)、C#通用数据库操作类 支持Access/MSSql/Orale/MySql等数据库的实用信息。
本文目录一览:- 如何开发支持oracle和mssql双版本数据库的产品(oracle数据库开发工具)
- Bool支持Oracle SQL
- C# 多数据库组件包,支持 MSSQL+Oracle+MySQL + 用户操作手册 | C/S 开发框架
- c#几种数据库的大数据批量插入(SqlServer、Oracle、SQLite和MySql)
- C#通用数据库操作类 支持Access/MSSql/Orale/MySql等数据库
如何开发支持oracle和mssql双版本数据库的产品(oracle数据库开发工具)
我们公司开发的产品需要支持oracle和mssql两种数据库:a.使用ibatis的产品中,一般预先编写两份xml文件内容为使用不同数据库特性的sql,然后使用ant命令build成两份;b.使用jdbcTemplate等类在代码中嵌入sql的产品中,如果使用一堆if..else会让代码显得臃肿,我的做法是面向接口编程,使用java多态的特性,引入工具类,简化代码。下面介绍第二种场景的解决办法。
第一步,建立两份properties文件,写入键值对标记当前数据库类型,然后交由ant工具build,如/WEB-INF/classes/common.properties,写入dbtype=oracle或dbtype=mssql。
第二步,创建属性文件读取bean,并在Spring配置文件中引入该bean。
a.属性文件读取bean:
public class CustomizedPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private static Map ctxPropertiesMap;
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
throws BeansException {
super.processProperties(beanFactoryToProcess, props);
ctxPropertiesMap = new HashMap();
for (Iterator iterator = props.keySet().iterator(); iterator.hasNext();) {
String keyStr = (String) iterator.next();
String value = props.getProperty(keyStr);
ctxPropertiesMap.put(keyStr, value);
}
}
public static Object getContextProperty(String name) {
return ctxPropertiesMap.get(name);
}
}
b.Spring配置:
<bean id="propertyConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>/WEB-INF/classes/common.properties</value>
</list>
</property>
</bean>
第二步,创建数据库特性语法转换接口和oracle、mssql实现类。
a.接口类:
public interface ConvertTo {
public String getDate();
/**
* 日期转换为字符串(格式:2013-05-16 10:57:49)
* @param dateColumn
* @return
*/
public String getFormatDatetime(String dateColumn);
/**
* 替换空字段为指定字符
* @param column
* @param replaceValue
* @return
*/
public String getIsNULL(String column,String replaceValue);
/**
* 判断子串是否存在
* @param sourceString
* @param targetString
* @return
*/
public String getInstr(String sourceString, String targetString);
/**
* 取前n条记录
* @param sql
* @param columnCount
* @return
*/
public String getFirstServeralColumns(String sql, int columnCount);
public String getFunction(String sql);
public String getStrLink();
public String getFromDual();
}
b.oracle实现类:
public class ConvertToOracle implements ConvertTo {
public String toDate(String dateText) {
return "to_date( " + dateText + " , ''YYYY-MM-DD'')";
}
public String getFormatDatetime(String dateColumn) {
return " to_char( "+dateColumn+" , ''YYYY-MM-DD hh:mm:ss'')";
}
/**
*获取当前日期的sql串
* @return
*/
public String getDate(){
return " sysDate ";
}
public String getIsNULL(String column,String replaceValue) {
return " NVL(" + column + "," + replaceValue + ") ";
}
/**
* 判断子串是否存在
*/
public String getInstr(String sourceString, String targetString) {
return " INSTR("+sourceString+","+targetString+")>0 ";
}
/**
* 取前n条记录
* @param sql
* @param columnCount
* @return
*/
public String getFirstServeralColumns(String sql, int columnCount) {
if(StringUtils.isBlank(sql) && columnCount<0) {
return null;
}
return " SELECT * FROM ("+sql+") VIVID WHERE ROWNUM<="+columnCount +" ";
}
/**
* 返回函数
*/
public String getFunction(String sql) {
if(StringUtils.isBlank(sql)) {
return null;
}
return " TABLE("+sql+") ";
}
public String getStrLink() {
return " || ";
}
public String getFromDual() {
return " from dual ";
}
}
c.mssql实现类:
public class ConvertToSQL implements ConvertTo {
public String getFormatDatetime(String dateColumn) {
return " CONVERT(varchar(100), "+dateColumn+", 120)";
}
/**
* 获取当前日期的sql串
*
* @return
*/
public String getDate() {
return " getDate() ";
}
public String getIsNULL(String column, String replaceValue) {
return " isNull(" + column + "," + replaceValue + ") ";
}
/**
* 判断子串是否存在
*/
public String getInstr(String sourceString, String targetString) {
return " CHARINDEX("+targetString+","+sourceString+")>0 ";
}
/**
* 取前n条记录
* @param sql
* @param columnCount
* @return
*/
public String getFirstServeralColumns(String sql, int columnCount) {
if(StringUtils.isBlank(sql) && columnCount<0) {
return null;
}
return " SELECT TOP "+columnCount+" * FROM ("+sql+") VIVID ";
}
/**
* 返回函数
*/
public String getFunction(String sql) {
if(StringUtils.isBlank(sql)) {
return null;
}
return sql;
}
public String getStrLink() {
return " + ";
}
public String getFromDual() {
return "";
}
}
第三步,创建接口调用辅助类。
<!-- lang: java -->
public class ConvertHelper {
private static Map convertToMap;
private ConvertHelper() { }
private static synchronized void syncInit() {
if(convertToMap==null) {
convertToMap = new HashMap();
convertToMap.put("oracle", new ConvertToOracle());
convertToMap.put("mssql", new ConvertToSQL());
}
}
private static Map getConvertToMap() {
if(convertToMap==null) {
syncInit();
}
return convertToMap;
}
public static ConvertTo getConvertTo(){
String dbtype = PropertyPlaceholderConfigurer.getProperty("dbtype");
return (ConvertTo)getConvertToMap().get(dbtype);
}
}
第四步,如何使用。
业务代码中获取ConvertTo对象,直接调用相关方法。如获取前5条用户数据:
ConvertTo convertTo = ConvertHelper.getConvertTo();
String mSql = getFirstServeralColumns(''SELECT * FROM TEST_USERS'',10);
Bool支持Oracle SQL
即使是问汤姆网站也对这种不合适感到沮丧,报告你应该将布尔列编码为固定值’Y’/’N’CHAR列,这是一个如此糟糕的副作用答案在很多不同的层面上我不知道从哪里开始批评它.事实上,这种响应的唯一赎回质量是(据我最近发现),许多其他数据库引擎也不支持布尔数据类型.
无论如何 – 问题……
我有一个解决以下问题的方法(虽然凌乱和冗长),所以我出于好奇而不是必要来问这个问题.但是让我感到惊讶的少数事情之一就是聪明的程序员的聪明才智,所以希望你们中的一个人能够提出以下解决方案.
在下面的示例中,函数stock_pkg.is_in_stock()(这是我的应用程序的固有部分)返回BOOL值,导致sql无效(请记住,sql不支持BOOL):
SELECT part_no,stock_pkg.is_in_stock(part_no) in_stock FROM parts_table
我需要的是找到一种方法使用上面的函数调用生成格式的有效字符串(varchar)输出:
PART_NO IN_STOCK ------- ------------ AA YES BB NO CC NO
(你可以用’是/否’代替’真/假’,’绿/红’,’保守/劳工’或甚至数字1/0代替我所关心的 – 只要输出属于两个不同的输出之一类别.)
不幸的是,我没有权限重写原始函数以返回不同的数据类型.此外,在这个较大的应用程序中有数千个这样的函数,这使得重写它们变得不切实际.
因此,从这个意义上讲,解决方案必须是“通用”解决方案(即不特定于此函数调用).例如,将函数重写为stock_pkg.is_in_stock_chr()是不够的,因为这意味着必须重新编写应用程序中的所有其他类似函数.
我已经尝试过了:
SELECT part_no,CASE WHEN stock_pkg.is_in_stock(part_no) THEN 'y' ELSE 'n' END in_stock FROM parts_table
甚至我自己的包装函数:
SELECT part_no,my_bool_to_str(stock_pkg.is_in_stock(part_no)) in_stock FROM parts_table
但是,即使在其他功能结构中包含布尔值也不会被Oracle sql所允许(至少在Oracle 10g中不允许).
还有在in_stock列中编写子选择的选项,但在极端的例子中也可能过于复杂,并且也可能是特定于案例的.
正如我所说,我希望在那里有一个巧妙的解决方案(或者至少是一个我碰巧忽略的非常简单的解决方案).
谢谢你的时间.
CREATE OR REPLACE FUNCTION my_bool_to_str(f varchar2) RETURN VARCHAR2 IS b varchar2(2); BEGIN EXECUTE IMMEDIATE 'declare bl boolean; begin bl := ' || f || '; if bl then :1 := ''y''; else :1 := ''n''; end if; end;' using out b; return b; END;
然后你可以像这样调用它:
SELECT part_no,my_bool_to_str('stock_pkg.is_in_stock('|| part_no|| ')') in_stock FROM parts_table
与包装器的不同之处在于它将varchar作为输入而不是sql引擎无法识别的布尔值
C# 多数据库组件包,支持 MSSQL+Oracle+MySQL + 用户操作手册 | C/S 开发框架
C# 多数据库组件包支持 MSSQL+Oracle+MySQL + 用户操作手册 | C/S 框架网

我们在开发软件过程中,特别是基于数据管理应用相关的系统,一般采用一种数据库,如 Microsoft SQL Server,超大型系统有的使用 Oracle,部分 Web 系统采用开源的 MySQL 等,由于各种业务场景以及用户需求,促使我们的数据库系统部署在不同类型的数据库服务器上。若开发的系统能支持多种数据库的快速切换,可以为我们减少很多烦恼,同时提高系统的适应性、兼容性以及可扩展性。


/// <summary>
/// IDatabase 数据库接口
/// </summary>
public interface IDatabase : IAdoFactory
{
int DefaultPort { get; }
int CommandTimeout { get; }
int ConnectionTimeout { get; }
Type DateTimeType { get; }
DateTime GetServerTime();
String ConnectionString { get; set; }
DbTransaction TransBegin();
void TransCommit(DbTransaction trans, bool closeConnection = false);
void TransRollback(DbTransaction trans, bool closeConnection = false);
DataSet GetDataSet(string SQL);
DataSet GetDataSet(DbCommand cmd);
DataSet GetDataSet(string text, CommandType type, IDataParameter[] paras);
DataTable GetTable(string SQL, string tableName = "");
DataTable GetTable(DbCommand cmd, string tableName = "");
DataRow GetDataRow(string SQL);
int ExecuteSQL(string SQL);
int ExecuteCommand(DbCommand cmd);
object ExecuteScalar(string SQL);
object ExecuteScalar(DbCommand cmd);
DbDataReader ExecuteReader(string SQL);
DbDataReader ExecuteReader(DbCommand cmd);
List<T> ExecuteReader<T>(string SQL, Func<DbDataReader, T> action) where T : new();
List<T> ExecuteReader<T>(DbCommand cmd, Func<DbDataReader, T> action) where T : new();
T ExecuteReader<T>(DbCommand cmd) where T : new();
T ExecuteReader<T>(string SQL) where T : new();
int ExecuteTrans(DbTransaction trans, string SQL);
void Close(DbConnection connection);
}
// 来源:C/S 框架网 (www.csframework.com) QQ:23404761
/// <summary>
/// ADO (ActiveX Data Object) ADO.NET 活动数据对象工厂
/// </summary>
public interface IAdoFactory
{
string BuildConnectionString(string server, int port, string dbName, string uid, string pwd, int timeout = 10);
CommandHelper CreateSqlProc(string spName);
CommandHelper CreateCommand(string commandText);
/// <summary>
/// DbCommand 的参数符号,@,?
/// </summary>
string ParamSymboName { get; }
DbParameter CreateTimestampParameter(string parameterName, string fieldName);
DbConnection CreateConnection();
DbConnection CreateConnection(string connectionString);
DbCommand CreateCommand(string commandText, CommandType commandType);
DbParameter CreateParameter(string parameterName, object parameterValue);
DbCommandBuilder CreateCommandBuilder();
DbDataAdapter CreateDataAdapter();
DbDataAdapter CreateDataAdapter(AdapterRowUpdatingEvent eventHandler);
}
// 来源:C/S 框架网 (www.csframework.com) QQ:23404761
/// <summary>
/// 数据库对象工厂
/// </summary>
public static class DatabaseFactory
{
/// <summary>
/// 创建数据库(使用 DataProviderFactory 创建数据存取基础组件,通用版)
/// </summary>
/// <param name="providerType"> 数据库类型 </param>
/// <param name="connectionString"> 数据库连接字符串 </param>
/// <returns></returns>
public static IDatabase CreateMDB(DatabaseType providerType, string connectionString)
{
return new DatabaseMDB(providerType, connectionString);
}
/// <summary>
/// 创建 SQL Server 数据库
/// </summary>
/// <param name="connectionString"> 数据库连接字符串 </param>
/// <returns></returns>
public static IDatabase CreateSqlDatabase(string connectionString)
{
return new DatabaseMSSQL(connectionString);
}
/// <summary>
/// 创建 MySQL 数据库
/// </summary>
/// <param name="connectionString"> 数据库连接字符串 </param>
/// <returns></returns>
public static IDatabase CreateMySqlDatabase(string connectionString)
{
return new DatabaseMySQL(connectionString);
}
/// <summary>
/// 创建 Oracle 数据库
/// </summary>
/// <param name="connectionString"> 数据库连接字符串 </param>
/// <returns></returns>
public static IDatabase CreateOracleDatabase(string connectionString)
{
return new DatabaseOracle(connectionString);
}
/// <summary>
/// 创建数据库
/// </summary>
/// <param name="dbType"> 数据库类型 </param>
/// <param name="connectionString"> 数据库连接字符串 </param>
/// <returns></returns>
public static IDatabase CreateDatabase(DatabaseType dbType, string connectionString)
{
if (dbType == DatabaseType.SqlServer)
return new DatabaseMSSQL(connectionString);
if (dbType == DatabaseType.MySQL)
return new DatabaseMySQL(connectionString);
if (dbType == DatabaseType.Oracle)
return new DatabaseOracle(connectionString);
throw new Exception ("未支持的数据库类型!");
}
/// <summary>
/// 创建数据库
/// </summary>
/// <param name="dbType"> 数据库类型 </param>
/// <param name="connectionString"> 数据库连接字符串 </param>
/// <returns></returns>
public static IDatabase CreateDatabase(string dbType, string connectionString)
{
DatabaseType databaseType;
if (!Enum.TryParse<DatabaseType>(dbType, true, out databaseType))
throw new Exception ("不支持的数据库类型!");
if (databaseType == DatabaseType.SqlServer)
return new DatabaseMSSQL(connectionString);
if (databaseType == DatabaseType.MySQL)
return new DatabaseMySQL(connectionString);
if (databaseType == DatabaseType.Oracle)
return new DatabaseOracle(connectionString);
throw new Exception ("未支持的数据库类型!");
}
/// <summary>
/// ADO 组件工厂
/// </summary>
/// <param name="dbType"> 数据库类型 </param>
/// <param name="connectionString"> 数据连接字符串 </param>
/// <returns></returns>
public static IAdoFactory GetADOFactory(DatabaseType dbType, string connectionString)
{
return CreateDatabase(dbType, connectionString);
}
}
// 来源:C/S 框架网 (www.csframework.com) QQ:23404761

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,"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})",table.TableName),names,values); } }
以上最重要的一步,就是将DataTable转为数组的数组表示,即object[][],前数组的上标是列的个数,后数组是行的个数,因此循环Columns将后数组作为Parameter的值,也就是说,参数的值是一个数组。而insert语句与一般的插入语句没有什么不一样。
三、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,"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,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,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}",column.ColumnName); }); return string.Format("INSERT INTO {0}({1}) VALUES ({2})",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,"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,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,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}",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],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}",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,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()); } //获取 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万条数据各耗用的时间
数据库 |
耗用时间 |
Mssql | 00:00:02.9376300 |
Oracle | 00:00:01.5155959 |
sqlite | 00:00:01.6275634 |
MysqL | 00:00:05.4166891 |
C#通用数据库操作类 支持Access/MSSql/Orale/MySql等数据库
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
namespace DbHelper
{
/// <summary>
/// 通用数据库访问类,封装了对数据库的常见操作
///</summary>
public sealed class DbUtility
{
public string ConnectionString { get; set; }
private DbProviderFactory providerFactory;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="connectionString">数据库连接字符串</param>
/// <param name="providerType">数据库类型枚举,参见<paramref name="providerType"/></param>
public DbUtility(string connectionString, DbProviderType providerType)
{
ConnectionString = connectionString;
providerFactory = ProviderFactory.GetDbProviderFactory(providerType);
if (providerFactory == null)
{
throw new ArgumentException("Can''t load DbProviderFactory for given value of providerType");
}
}
/// <summary>
/// 对数据库执行增删改操作,返回受影响的行数。
/// </summary>
/// <param name="sql">要执行的增删改的SQL语句</param>
/// <param name="parameters">执行增删改语句所需要的参数</param>
/// <returns></returns>
public int ExecuteNonQuery(string sql, IList<DbParameter> parameters)
{
return ExecuteNonQuery(sql, parameters, CommandType.Text);
}
/// <summary>
/// 对数据库执行增删改操作,返回受影响的行数。
/// </summary>
/// <param name="sql">要执行的增删改的SQL语句</param>
/// <param name="parameters">执行增删改语句所需要的参数</param>
/// <param name="commandType">执行的SQL语句的类型</param>
/// <returns></returns>
public int ExecuteNonQuery(string sql, IList<DbParameter> parameters, CommandType commandType)
{
using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
{
command.Connection.Open();
int affectedRows = command.ExecuteNonQuery();
command.Connection.Close();
return affectedRows;
}
}
/// <summary>
/// 执行一个查询语句,返回一个关联的DataReader实例
/// </summary>
/// <param name="sql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数</param>
/// <returns></returns>
public DbDataReader ExecuteReader(string sql, IList<DbParameter> parameters)
{
return ExecuteReader(sql, parameters, CommandType.Text);
}
/// <summary>
/// 执行一个查询语句,返回一个关联的DataReader实例
/// </summary>
/// <param name="sql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数</param>
/// <param name="commandType">执行的SQL语句的类型</param>
/// <returns></returns>
public DbDataReader ExecuteReader(string sql, IList<DbParameter> parameters, CommandType commandType)
{
DbCommand command = CreateDbCommand(sql, parameters, commandType);
command.Connection.Open();
return command.ExecuteReader(CommandBehavior.CloseConnection);
}
/// <summary>
/// 执行一个查询语句,返回一个包含查询结果的DataTable
/// </summary>
/// <param name="sql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数</param>
/// <returns></returns>
public DataTable ExecuteDataTable(string sql, IList<DbParameter> parameters)
{
return ExecuteDataTable(sql, parameters, CommandType.Text);
}
/// <summary>
/// 执行一个查询语句,返回一个包含查询结果的DataTable
/// </summary>
/// <param name="sql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数</param>
/// <param name="commandType">执行的SQL语句的类型</param>
/// <returns></returns>
public DataTable ExecuteDataTable(string sql, IList<DbParameter> parameters, CommandType commandType)
{
using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
{
using (DbDataAdapter adapter = providerFactory.CreateDataAdapter())
{
adapter.SelectCommand = command;
DataTable data = new DataTable();
adapter.Fill(data);
return data;
}
}
}
/// <summary>
/// 执行一个查询语句,返回查询结果的第一行第一列
/// </summary>
/// <param name="sql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数</param>
/// <returns></returns>
public Object ExecuteScalar(string sql, IList<DbParameter> parameters)
{
return ExecuteScalar(sql, parameters, CommandType.Text);
}
/// <summary>
/// 执行一个查询语句,返回查询结果的第一行第一列
/// </summary>
/// <param name="sql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数</param>
/// <param name="commandType">执行的SQL语句的类型</param>
/// <returns></returns>
public Object ExecuteScalar(string sql, IList<DbParameter> parameters, CommandType commandType)
{
using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
{
command.Connection.Open();
object result = command.ExecuteScalar();
command.Connection.Close();
return result;
}
}
public DbParameter CreateDbParameter(string name, object value)
{
return CreateDbParameter(name, ParameterDirection.Input, value);
}
public DbParameter CreateDbParameter(string name, ParameterDirection parameterDirection, object value)
{
DbParameter parameter = providerFactory.CreateParameter();
parameter.ParameterName = name;
parameter.Value = value;
parameter.Direction = parameterDirection;
return parameter;
}
/// <summary>
/// 创建一个DbCommand对象
/// </summary>
/// <param name="sql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数</param>
/// <param name="commandType">执行的SQL语句的类型</param>
/// <returns></returns>
private DbCommand CreateDbCommand(string sql, IList<DbParameter> parameters, CommandType commandType)
{
DbConnection connection = providerFactory.CreateConnection();
DbCommand command = providerFactory.CreateCommand();
connection.ConnectionString = ConnectionString;
command.CommandText = sql;
command.CommandType = commandType;
command.Connection = connection;
if (!(parameters == null || parameters.Count == 0))
{
foreach (DbParameter parameter in parameters)
{
command.Parameters.Add(parameter);
}
}
return command;
}
}
/// <summary>
/// 数据库类型枚举
/// </summary>
public enum DbProviderType : byte
{
SqlServer,
MySql,
SQLite,
Oracle,
ODBC,
OleDb,
Firebird,
PostgreSql,
DB2,
Informix,
SqlServerCe
}
/// <summary>
/// DbProviderFactory工厂类
/// </summary>
public class ProviderFactory
{
private static Dictionary<DbProviderType, string> providerInvariantNames = new Dictionary<DbProviderType, string>();
private static Dictionary<DbProviderType, DbProviderFactory> providerFactoies = new Dictionary<DbProviderType, DbProviderFactory>(20);
static ProviderFactory()
{
//加载已知的数据库访问类的程序集
providerInvariantNames.Add(DbProviderType.SqlServer, "System.Data.SqlClient");
providerInvariantNames.Add(DbProviderType.OleDb, "System.Data.OleDb");
providerInvariantNames.Add(DbProviderType.ODBC, "System.Data.ODBC");
providerInvariantNames.Add(DbProviderType.Oracle, "Oracle.DataAccess.Client");
providerInvariantNames.Add(DbProviderType.MySql, "MySql.Data.MySqlClient");
providerInvariantNames.Add(DbProviderType.SQLite, "System.Data.SQLite");
providerInvariantNames.Add(DbProviderType.Firebird, "FirebirdSql.Data.Firebird");
providerInvariantNames.Add(DbProviderType.PostgreSql, "Npgsql");
providerInvariantNames.Add(DbProviderType.DB2, "IBM.Data.DB2.iSeries");
providerInvariantNames.Add(DbProviderType.Informix, "IBM.Data.Informix");
providerInvariantNames.Add(DbProviderType.SqlServerCe, "System.Data.SqlServerCe");
}
/// <summary>
/// 获取指定数据库类型对应的程序集名称
/// </summary>
/// <param name="providerType">数据库类型枚举</param>
/// <returns></returns>
public static string GetProviderInvariantName(DbProviderType providerType)
{
return providerInvariantNames[providerType];
}
/// <summary>
/// 获取指定类型的数据库对应的DbProviderFactory
/// </summary>
/// <param name="providerType">数据库类型枚举</param>
/// <returns></returns>
public static DbProviderFactory GetDbProviderFactory(DbProviderType providerType)
{
//如果还没有加载,则加载该DbProviderFactory
if (!providerFactoies.ContainsKey(providerType))
{
providerFactoies.Add(providerType, ImportDbProviderFactory(providerType));
}
return providerFactoies[providerType];
}
/// <summary>
/// 加载指定数据库类型的DbProviderFactory
/// </summary>
/// <param name="providerType">数据库类型枚举</param>
/// <returns></returns>
private static DbProviderFactory ImportDbProviderFactory(DbProviderType providerType)
{
string providerName = providerInvariantNames[providerType];
DbProviderFactory factory = null;
try
{
//从全局程序集中查找
factory = DbProviderFactories.GetFactory(providerName);
}
catch (ArgumentException e)
{
factory = null;
}
return factory;
}
}
}
//使用示例 SQLite
string connectionString = @"Data Source=D:\VS2008\NetworkTime\CrawlApplication\CrawlApplication.db3";
string sql = "SELECT * FROM Weibo_Media order by Id desc limit 0,20000";
DbUtility db = new DbUtility(connectionString, DbProviderType.SQLite);
DataTable data = db.ExecuteDataTable(sql, null);
DbDataReader reader = db.ExecuteReader(sql, null);
reader.Close();
//使用示例 MySql
string connectionString = @"Server=localhost;Database=crawldb;Uid=root;Pwd=root;Port=3306;";
string sql = "SELECT * FROM Weibo_Media order by Id desc limit 0,20000";
DbUtility db = new DbUtility(connectionString, DbProviderType.MySql);
DataTable data = db.ExecuteDataTable(sql, null);
DbDataReader reader = db.ExecuteReader(sql, null);
reader.Close();
//使用示例 Execl
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("~/XLS/车型.xls") + ";Extended Properties=Excel 8.0;";
string sql = "SELECT * FROM [Sheet1$]";
DbUtility db = new DbUtility(connectionString, DbProviderType.OleDb);
DataTable data = db.ExecuteDataTable(sql, null);
关于如何开发支持oracle和mssql双版本数据库的产品和oracle数据库开发工具的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Bool支持Oracle SQL、C# 多数据库组件包,支持 MSSQL+Oracle+MySQL + 用户操作手册 | C/S 开发框架、c#几种数据库的大数据批量插入(SqlServer、Oracle、SQLite和MySql)、C#通用数据库操作类 支持Access/MSSql/Orale/MySql等数据库等相关知识的信息别忘了在本站进行查找喔。
本文标签: