繁体中文
设为首页
加入收藏
当前位置:.Net技术首页 >> Asp.Net开发 >> 将DataSet更新自动提交到数据库工具类实现

将DataSet更新自动提交到数据库工具类实现

2007-09-15 08:00:00  作者:  来源:互联网  浏览次数:0  文字大小:【】【】【
简介:在项目中遇到一些要把DataSet的更改提交到数据库的需求,因此,实现了一个工具类来完成这个工作。 设计思想:DataSet中的每一个DataTable中的每一行都有状态(RowState), 并且DataTable提供了一个GetChanges(Data...

在项目中遇到一些要把DataSet的更改提交到数据库的需求,因此,实现了一个工具类来完成这个工作。

设计思想:DataSet中的每一个DataTable中的每一行都有状态(RowState), 并且DataTable提供了一个GetChanges(DataRowState state)的方法来获取变化了的数据集合,返回一个新的DataTable对象。因此,我们根据数据提交的顺序,将分别处理 Insert, Update, Delete三种情况,并且根据与数据库表的映射,自动构造SQL语句,利用SqlDataAdapter完成数据提交工作。

由于.net基础数据类型与SQL Server数据类型存在多对一的关系,且使用数据适配器(DataAdapter)时,构造SQL参数对象必须要求指定每个参数对象的长度以及更多信息(映射数据有版本的情况下),因此,不好根据DataColumn的类型来推导对应的SqlDbType,故根据需要实现了一个新的类,来保存每个列的映射及参数。

下面是实现的原代码,有许多需要改进的地方,希望大家提出更好的意见和建议。在此谢过,先!

using System;

using System.Data;

using System.Data.Common;

using System.Data.SqlClient;

using System.Text;

namespace kim.Data

{

///

/// Summary description for SqlDbAccess.

///

public class SqlDbAccess

{

static SqlDbAccess()

{

}

///

/// 处理传入的数据库表名,加上[],避免因表名是数据库中的关键字而出错。

/// 并且在不存在所有者名的时候,加上所有者名。

///

/// 待处理的数据库表名。

/// 处理后的数据库表名。

private static string PrepareDbTableName(string dbTableName)

{

string[] tableName = dbTableName.Split('.');

if(tableName.Length == 1) //只有表名

{

if(tableName[0][0] == '[')

return tableName[0]; // [tableName] 格式

else

return string.Concat("dbo.[", dbTableName, "]"); //tableName 格式

}

else

{

StringBuilder text = new StringBuilder(100);

for(int i=0; i

{

if(tableName[0] == '[') //[xx] 格式

text.Append(tableName[0] + '.');

else // xx 格式

text.Append("[" + tableName + "].");

}

text.Remove(text.Length-1, 1);

return text.ToString();

}

}

///

/// 更新DataTable的更改到数据库中。

/// 并发控制采用“最后的更新生效”

///

/// 有效的要提交的DataTable对象

/// 有效的数据为连接对象

/// 有效的数据库表名

/// 有效的要提交的列及参数映射对象数组

/// 有效的条件列及参数映射对象数组

/// 是否需要事务

public static void UpdateData(DataTable table, SqlConnection sqlConn, string dbTableName,

ParameterColumnMapping[] dataColumnMappings, ParameterColumnMapping[] keyColumnMappings, bool needTransaction)

{

if(table == null) throw new ArgumentNullException("table");

if(sqlConn == null) throw new ArgumentNullException("sqlConn");

if(dbTableName == null || dbTableName.Length == 0) throw new ArgumentNullException("dbTableName");

if(dataColumnMappings == null || dataColumnMappings.Length == 0) throw new ArgumentNullException("dataColumnMappings");

if(keyColumnMappings == null || keyColumnMappings.Length == 0) throw new ArgumentNullException("keyColumnMappings");

if(table.Rows.Count == 0) return;

dbTableName = PrepareDbTableName(dbTableName);

// 设置连接是否需要在完成后关闭的标记。

// 如果连接对象传进来时是关闭的,则用完后也应该关闭。即保持连接传入前的状态。

bool connNeedClose = (sqlConn.State == ConnectionState.Closed);

SqlDataAdapter sqlAdapter = new SqlDataAdapter();

// 添加表映射及列映射

DataTableMapping tableMapping = sqlAdapter.TableMappings.Add(dbTableName, table.TableName);

for(int i=0; i

{

tableMapping.ColumnMappings.Add(dataColumnMappings.SourceColumn, dataColumnMappings.DataTableColumn);

}

// 构造WHERE条件部分

StringBuilder sqlWhere = new StringBuilder(256);

sqlWhere = new StringBuilder(256);

sqlWhere.Append(" WHERE ");

for(int i=0; i

{

if(i == 0)

{

sqlWhere.Append(string.Format("[{0}] = @{0}", keyColumnMappings.SourceColumn));

}

else

{

sqlWhere.Append(string.Format(" AND [{0}] = @{0}", keyColumnMappings.SourceColumn));

}

}

StringBuilder sqlText = new StringBuilder(1024);

SqlTransaction sqlTran = null;

DataTable tempTable = null;

DataRow[] rows = new DataRow[1];

// 开始提交数据

try

{

if(connNeedClose) sqlConn.Open();

if(needTransaction) sqlTran = sqlConn.BeginTransaction();

SqlCommand sqlCmd = new SqlCommand("", sqlConn, sqlTran);

// 处理Insert

tempTable = table.GetChanges(DataRowState.Added);

if(tempTable != null)

{

sqlAdapter.InsertCommand = sqlCmd;

StringBuilder valueText = new StringBuilder(256);

// 循环每一行,只处理不为Null的列

foreach(DataRow dr in tempTable.Rows)

{

sqlCmd.Parameters.Clear();

sqlText.Length = 0;

sqlText.Append("INSERT INTO " + dbTableName + " (");

for(int i=0; i

{

if(dr[dataColumnMappings.DataTableColumn] != DBNull.Value)

{

sqlText.Append(string.Format(" [{0}],", dataColumnMappings.SourceColumn));

valueText.Append(string.Format(" @{0},", dataColumnMappings.SourceColumn));

sqlCmd.Parameters.Add(dataColumnMappings.DbParameter);

}

}

// 移除末尾的','

sqlText.Remove(sqlText.Length-1, 1);

valueText.Remove(valueText.Length-1, 1);

// 完成Insert语句的构造并提交

sqlText.Append(string.Format(" ) VALUES ({0})", valueText.ToString()));

sqlCmd.CommandText = sqlText.ToString();

rows[0] = dr;

sqlAdapter.Update(rows);

}

}

// 处理Update

// 仅对已经发生了改变的列进行Update

tempTable = table.GetChanges(DataRowState.Modified);

if(tempTable != null)

{

int changedColumns = 0; //用于记录已经改变的列数

sqlAdapter.UpdateCommand = sqlCmd;

foreach(DataRow dr in tempTable.Rows)

{

sqlCmd.Parameters.Clear();

sqlText.Length = 0;

sqlText.Append(string.Format("UPDATE {0} SET", dbTableName));

changedColumns = 0;

for(int i=0; i

{

// 当前版本与原始版本不等

if(!dr[dataColumnMappings.DataTableColumn, DataRowVersion.Current].Equals(

dr[dataColumnMappings.DataTableColumn, DataRowVersion.Original]))

{

sqlText.Append(string.Format(" [{0}]=@{0},", dataColumnMappings.SourceColumn));

sqlCmd.Parameters.Add(dataColumnMappings.DbParameter);

changedColumns ++;

}

}

// 仅当有列改变了才进行处理,以防止行状态改变了,但值未变的情况。

if(changedColumns > 0)

{

sqlText.Remove(sqlText.Length-1, 1); //移除末尾的‘,'

sqlText.Append(" " + sqlWhere.ToString());

// 添加条件参数

for(int j=0; j

{

sqlCmd.Parameters.Add(keyColumnMappings[j].DbParameter);

}

// 提交数据

sqlCmd.CommandText = sqlText.ToString();

rows[0] = dr;

sqlAdapter.Update(rows);

}

}

}

// 处理Delete

tempTable = table.GetChanges(DataRowState.Deleted);

if(tempTable != null && tempTable.Rows.Count > 0)

{

sqlText.Length = 0;

sqlText.Append("DELETE FROM " + dbTableName + sqlWhere.ToString());

sqlCmd.CommandText = sqlText.ToString();

sqlCmd.Parameters.Clear();

// 添加条件参数

for(int j=0; j

{

sqlCmd.Parameters.Add(keyColumnMappings[j].DbParameter);

}

sqlAdapter.DeleteCommand = sqlCmd;

sqlAdapter.Update(tempTable);

}

if(sqlTran != null) sqlTran.Commit();

}

catch(Exception ex)

{

if(sqlTran != null)

{

sqlTran.Rollback();

}

throw ex;

}

finally

{

if(connNeedClose) sqlConn.Close();

}

}

///

/// 定义参数与列的映射关系的类。

///

public class ParameterColumnMapping

{

private string m_SourceColumn;

private string m_DataTableColumn;

private SqlParameter m_DbParameter;

///

/// 构造函数。

///

/// 数据库源列名

/// DataTable中的列名

/// 对应的参数对象

public ParameterColumnMapping(string sourceColumn, string dataTableColumn, SqlParameter dbParameter)

{

m_SourceColumn = sourceColumn;

m_DataTableColumn = dataTableColumn;

m_DbParameter = dbParameter;

SetParameterSourceColumn();

}

public ParameterColumnMapping() : this(null, null, null)

{

}

///

/// 获取或设置数据库源列名。

///

public string SourceColumn {

get {

return m_SourceColumn;

}

set {

m_SourceColumn = value;

}

}

///

/// 获取或设置DataTable对象中的列名。

///

public string DataTableColumn {

get {

return m_DataTableColumn;

}

set {

m_DataTableColumn = value;

}

}

///

/// 获取或设置列对应的Sql参数对象。

///

public SqlParameter DbParameter {

get {

return m_DbParameter;

}

set {

m_DbParameter = value;

SetParameterSourceColumn();

}

}

private void SetParameterSourceColumn()

{

if((m_DbParameter.SourceColumn == null || m_DbParameter.SourceColumn == string.Empty)

&& (m_DataTableColumn != null && m_DataTableColumn != string.Empty))

{

m_DbParameter.SourceColumn = m_DataTableColumn;

}

}

}

}

}

**************************************************

SqlDbAccess.ParameterColumnMapping[] dataColumnMappings = new kim.Data.SqlDbAccess.ParameterColumnMapping[2];

dataColumnMappings[0] = new kim.Data.SqlDbAccess.ParameterColumnMapping("APP_ID", myData.AppSystems.AppIDColumn.ColumnName,

new SqlParameter("@APP_ID", SqlDbType.NVarChar, 20, myData.AppSystems.AppIDColumn.ColumnName));

dataColumnMappings[1] = new kim.Data.SqlDbAccess.ParameterColumnMapping("DESCRIPTION", myData.AppSystems.DescriptionColumn.ColumnName,

new SqlParameter("@DESCRIPTION", SqlDbType.NVarChar, 500, myData.AppSystems.DescriptionColumn.ColumnName));

SqlDbAccess.ParameterColumnMapping[] keyColumnMappings = new kim.Data.SqlDbAccess.ParameterColumnMapping[1];

keyColumnMappings[0] = new kim.Data.SqlDbAccess.ParameterColumnMapping("APP_ID", myData.AppSystems.AppIDColumn.ColumnName,

new SqlParameter("@APP_ID", SqlDbType.NVarChar, 20, ParameterDirection.Input, true, 0, 0, myData.AppSystems.AppIDColumn.ColumnName, DataRowVersion.Original, null));

SqlConnection sqlConn = new SqlConnection(Configuration.D2WHP01_ConnString);

SqlDbAccess.UpdateData(myData.AppSystems, sqlConn, "AzProvider.dbo.APP", dataColumnMappings, keyColumnMappings, true);

ps: 缺点:使用sqlAdapter.Update,因为他是每条数据更新一次(效率比较低)

责任编辑:admin
相关文章