强类型Dataset使用事务(改进原有方法)

原创 2015年11月21日 16:11:44

以下部份转自:http://blog.csdn.net/nfbing/article/details/5803980


关于强类型Dataset的用法和好处,我就不再多说,网上关于这方面的资料很多 , 感兴趣的话可以在GoOGLE搜一下。

我们直奔主题,好处是很多,但若使用事务的话就不方便了。最近通过查找国外的资料,总于找到解决的方法。经过自己测试发现很好用,所以把代码贴出来,给正处于这方面困惑的朋友解答:

 

首先写一个类文件,代码如下:

 

    public class HelperTA
    {

        public static SqlTransaction BeginTransaction(object tableAdapter)
        {
            return BeginTransaction(tableAdapter, IsolationLevel.ReadUncommitted);
        }

        public static SqlTransaction BeginTransaction(object tableAdapter, IsolationLevel isolationLevel)
        {
            // get the table adapter's type
            Type type = tableAdapter.GetType();

            // get the connection on the adapter
            SqlConnection connection = GetConnection(tableAdapter);

            // make sure connection is open to start the transaction
            if (connection.State == ConnectionState.Closed)
                connection.Open();

            // start a transaction on the connection
            SqlTransaction transaction = connection.BeginTransaction(isolationLevel);

            // set the transaction on the table adapter
            SetTransaction(tableAdapter, transaction);

            return transaction;
        }

        /// <summary>
        /// Gets the connection from the specified table adapter.
        /// </summary>
        private static SqlConnection GetConnection(object tableAdapter)
        {
            Type type = tableAdapter.GetType();
            PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
            SqlConnection connection = (SqlConnection)connectionProperty.GetValue(tableAdapter, null);
            return connection;
        }

        /// <summary>
        /// Sets the connection on the specified table adapter.
        /// </summary>
        private static void SetConnection(object tableAdapter, SqlConnection connection)
        {
            Type type = tableAdapter.GetType();
            PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
            connectionProperty.SetValue(tableAdapter, connection, null);
        }

        /// <summary>
        /// Enlists the table adapter in a transaction.
        /// </summary>
        public static void SetTransaction(object tableAdapter, SqlTransaction transaction)
        {
            // get the table adapter's type
            Type type = tableAdapter.GetType();

            // set the transaction on each command in the adapter
            PropertyInfo commandsProperty = type.GetProperty("CommandCollection", BindingFlags.NonPublic | BindingFlags.Instance);
            SqlCommand[] commands = (SqlCommand[])commandsProperty.GetValue(tableAdapter, null);
            foreach (SqlCommand command in commands)
                command.Transaction = transaction;

            // set the connection on the table adapter
            SetConnection(tableAdapter, transaction.Connection);
        }
    }
 

 

然后在你使用TableAdapter 的类文件中使用上面的类:

 

        public int InsertTest(Book book)
        {
            SqlTransaction transaction = null;

            try
            {
                int? myresult = 0;
                using (SKUTableAdapter barAdapter = new SKUTableAdapter())
                {
                    transaction = HelperTA .BeginTransaction(barAdapter);
                    barAdapter.SP_InsertSku("dfsdf", "contentname", 2, "", ref myresult);
                }

                using (UserEvaluateTableAdapter EvaluateAdapter = new UserEvaluateTableAdapter())
                {
                    HelperTA .SetTransaction(EvaluateAdapter, transaction);
                    EvaluateAdapter.InsertQuery(Guid.NewGuid().ToString(), "username", "szevaluate", 2);
                }

                int? result = 0;
                using (tb_BookTableAdapter bookadapter = new tb_BookTableAdapter())
                {
                    HelperTA .SetTransaction(bookadapter, transaction);
                    bookadapter.SP_CheckDuplicateEbook("title", "code", 2, System.DateTime.Now, ref result);
                }

                transaction.Commit();
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
            finally
            {
                transaction.Dispose();
            }

            return 1;
        }


以上内容转自nfbing的专栏:http://blog.csdn.net/nfbing/article/details/5803980


使用后发现不能针对TableAdapter自动生成的Insert/Update/Delete进行事务处理,可以对添加的查询(SQL或者存储过程)进行事务处理。所以如果想使用xxTableAdapter.Update(xxTable)一类的更新就有问题了。方法是自己写代码为TableAdapter加带事务的方法,但没有这个通用性好,需要每个去编写。


经过实验,将原来的代码部份更改,并更新相应的TableAdapter类即可实现较好的效果:


更新后类代码:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;

/// <summary>
/// 为强类型的DataSet中的TableAdapter提供事务支持
/// </summary>
public class HelperTA
{
    /// <summary>
    /// 开始事务,第一个tableAdapter中使用,接受脏读
    /// </summary>
    /// <param name="tableAdapter"></param>
    /// <returns>返回一个SqlTransaction</returns>
    public static SqlTransaction BeginTransaction(object tableAdapter)
    {
        return BeginTransaction(tableAdapter, IsolationLevel.ReadUncommitted);
    }

    /// <summary>
    /// 开始事务,第一个tableAdapter中使用,可设置接受脏读及其它参数
    /// </summary>
    /// <param name="tableAdapter"></param>
    /// <param name="isolationLevel">事务锁定行为</param>
    /// <returns>返回一个SqlTransaction</returns>
    public static SqlTransaction BeginTransaction(object tableAdapter, IsolationLevel isolationLevel)
    {
        // get the table adapter's type
        Type type = tableAdapter.GetType();

        // get the connection on the adapter
        SqlConnection connection = GetConnection(tableAdapter);

        // make sure connection is open to start the transaction
        if (connection.State == ConnectionState.Closed)
            connection.Open();

        // start a transaction on the connection
        SqlTransaction transaction = connection.BeginTransaction(isolationLevel);

        // set the transaction on the table adapter
        SetTransaction(tableAdapter, transaction);

        return transaction;
    }

    /// <summary>
    /// Gets the connection from the specified table adapter.
    /// </summary>
    private static SqlConnection GetConnection(object tableAdapter)
    {
        Type type = tableAdapter.GetType();
        PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
        SqlConnection connection = (SqlConnection)connectionProperty.GetValue(tableAdapter, null);
        return connection;
    }

    /// <summary>
    /// 设置 table adapter 的连接属性(自动调用)
    /// </summary>
    private static void SetConnection(object tableAdapter, SqlConnection connection)
    {
        Type type = tableAdapter.GetType();
        PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
        connectionProperty.SetValue(tableAdapter, connection, null);
    }

    /// <summary>
    /// 将新的tableAdapter加入到事务中
    /// </summary>
    /// <param name="tableAdapter"></param>
    /// <param name="transaction"></param>
    public static void SetTransaction(object tableAdapter, SqlTransaction transaction)
    {
        // get the table adapter's type
        Type type = tableAdapter.GetType();

        // set the transaction on each command in the adapter
        PropertyInfo commandsProperty = type.GetProperty("CommandCollection", BindingFlags.NonPublic | BindingFlags.Instance);
        SqlCommand[] commands = (SqlCommand[])commandsProperty.GetValue(tableAdapter, null);
        foreach (SqlCommand command in commands)
            command.Transaction = transaction;

        //设置自动生成的增、删、改命令事务
        PropertyInfo AdapterProperty = type.GetProperty("Adapter", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Static);
        SqlDataAdapter adapter = (SqlDataAdapter)AdapterProperty.GetValue(tableAdapter, null);
        if (adapter.InsertCommand != null) adapter.InsertCommand.Transaction = transaction;
        if (adapter.UpdateCommand != null) adapter.UpdateCommand.Transaction = transaction;
        if (adapter.DeleteCommand != null) adapter.DeleteCommand.Transaction = transaction;


        // set the connection on the table adapter
        SetConnection(tableAdapter, transaction.Connection);
    }
}


关于DataSet事务处理以及SqlDataAdapter四种用法

如果是直接执行SQL语句时,事务很好处理,对于大多数的Erp应用,不能能用SQL来处理数据,所以更新DataSet更为常用,更新单个的DataSet也非常简单,不需要事务的处理,给多个DataSet增...
  • lin_lujian
  • lin_lujian
  • 2011年10月28日 13:18
  • 536

强类型的DataSet

我们经常都在使用DataSet进行数据操作,使用起来或许非常的方便,但是我们有没有考虑过它的一些不足呢(比如:在进行操作的时候总要编写许多的代码)!以前我也是觉得在操作数据的时候非常方便,别的什么也没...
  • krenyelang
  • krenyelang
  • 2011年09月09日 19:02
  • 2501

强类型Dataset使用事务

关于强类型Dataset的用法和好处,我就不再不多说,网上关于这方面的资料很多 , 感兴趣的话可以在GoOGLE搜一下。我们直奔主题,好处是很多,但若使用事务的话就不方便了。最近通过查找国外的资料,总...
  • nfbing
  • nfbing
  • 2010年08月11日 13:58
  • 993

类型化(Type)的DataSet (使用强类型的DataSet。定义的数据库表一定要有主键,否则不能使用)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using 可空类型.Dat...
  • Fanbin168
  • Fanbin168
  • 2013年09月03日 23:57
  • 1156

重置强类型DataSet的数据库连接字符串

办法: tB_XXXXXXXTableAdapter1.Connection.ConnectionString = newConnectionString; 不需要对自动生成的类做任务修改。...
  • penginpha
  • penginpha
  • 2011年11月09日 15:44
  • 1297

[C#]强类型

首先声明,这篇文章仅仅是个人的学习体会,并不是标准资料。如果有什么谬误,欢迎高手指出。object o1 = new object();string s1 = o1.ToString();    //...
  • wwwsq
  • wwwsq
  • 2004年12月31日 15:16
  • 3747

强类型DataSet几点注意事项

强类型DataSet使用: 1项目-->新建项-->Data-->数据集-->*.xsd文件-->拖拽服务器资源管理器中数据库文件DataSet设计器窗口中。系统会自动帮我们生成Fill,和GetD...
  • zxkevin1989
  • zxkevin1989
  • 2011年04月19日 16:28
  • 1675

强类型数据集

在日常开发中,为了编写数据的增加、更新、修改、删除等功能而不得不面对枯燥的代码,做重复又重复的工作。.NET 2.0正式版的发布,对我们程序开发人员来说无疑是一件很大的喜事,Visual Studio...
  • shankaipingo
  • shankaipingo
  • 2006年09月18日 16:14
  • 1065

非强类型dataset 和 强类型dataset 比较

以表名"MyTable",及字段 FirstName varchar(30),FamilyName varchar(30)为例非强类型(UnTyped)Dataset 无需预先定义对应表的各个字段的属...
  • an9el
  • an9el
  • 2005年07月28日 00:39
  • 3277

使用webservice操作强类型数据集时的注意事项

使用WebService和强类型数据集进行数据操作  作者野人,转载注明出处 首先我推荐使用.NET提供的强类型数据集,理由最少有5个: 1、对象化数据访问 2、强制类型检查 3、可视化 4...
  • zyqjfzy
  • zyqjfzy
  • 2015年02月06日 19:18
  • 316
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:强类型Dataset使用事务(改进原有方法)
举报原因:
原因补充:

(最多只允许输入30个字)