您的位置:首页 > 其它

有关Transaction的错误提示及正确的处理

2010-01-25 12:49 363 查看
我也遇到类似的问题:

最近在写代码中处理事务的时候出现了几个问题,现在整理一下贴到网上。本文除特别指明外,均采用DAAB 3.1的Odbc类连接Sybase 9.1.2。
1.当分配给命令的连接处于挂起的本地事务中时,命令必须具有事务对象才能执行。该命令的 Transaction 属性尚未初始化。
问题出现的原因是Transaction并没有初始化。不过由于DAAB的Odbc类对ADO.Net的一些方法和类进行了封装,可能读者并不清楚需要何时初始化。下面我们来看一段错误的代码。

string connstr=ConfigurationSettings.AppSettings["SQLconnstr"];
OdbcConnection conn=new OdbcConnection(connstr);
conn.Open();
OdbcTransaction transaction=conn.BeginTransaction();
try
{
OdbcParameter [] searchParms = new OdbcParameter[1];
searchParms[0] = new OdbcParameter("@bh",OdbcType.VarChar);
searchParms[0].Value = "0000000001";
odbc.ExecuteNonQuery(conn,"delYsqlBxMx",searchParms);
throw new Exception("to see if the transaction rollback");
foreach(DataRow dr in BXCredDS.Tables[BaoXiaoPingZhengData.BAOXIAOMINGXI_TABLE].Rows)
{
searchParms = new OdbcParameter[4];
searchParms[0]=new OdbcParameter("@bh",OdbcType.VarChar);
searchParms[1] = new OdbcParameter("@xh",OdbcType.Int);
searchParms[2]=new OdbcParameter("@code",OdbcType.VarChar);
searchParms[3]=new OdbcParameter("@je",OdbcType.Double);
searchParms[0].Value="0000000001";
searchParms[1].Value=Convert.ToInt32(dr[BaoXiaoPingZhengData.XUHAO_FIELD]);
searchParms[2].Value=dr[BaoXiaoPingZhengData.CODE_FIELD].ToString();
searchParms[3].Value=Convert.ToDecimal(dr[BaoXiaoPingZhengData.SUM_FIELD]);
odbc.ExecuteNonQuery(conn,"insertYsqlBxMx",searchParms);
}

transaction.Commit();
conn.Close();
}
catch(Exception ex)
{
transaction.Rollback();
conn.Close();
throw ex;
}

这段代码运行后会出现上面的错误,通过调试发现,ExecuteNonQuery方法内部创建的Command对象的Transaction属性并没有赋值,因此我们需要这样写
odbc.ExecuteNonQuery(transaction,"delYsqlBxMx",searchParms);
2.无提示错误,但事务没有执行。(不易发现)

string connstr=ConfigurationSettings.AppSettings["SQLconnstr"];
OdbcConnection conn=new OdbcConnection(connstr);
conn.Open();
OdbcTransaction transaction=conn.BeginTransaction();
try
{
OdbcParameter [] searchParms = new OdbcParameter[1];
searchParms[0] = new OdbcParameter("@bh",OdbcType.VarChar);
searchParms[0].Value = "0000000001";
odbc.ExecuteNonQuery(connstr,"delYsqlBxMx",searchParms);
throw new Exception("to see if the transaction rollback");
foreach(DataRow dr in BXCredDS.Tables[BaoXiaoPingZhengData.BAOXIAOMINGXI_TABLE].Rows)
{
searchParms = new OdbcParameter[4];
searchParms[0]=new OdbcParameter("@bh",OdbcType.VarChar);
searchParms[1] = new OdbcParameter("@xh",OdbcType.Int);
searchParms[2]=new OdbcParameter("@code",OdbcType.VarChar);
searchParms[3]=new OdbcParameter("@je",OdbcType.Double);
searchParms[0].Value="0000000001";
searchParms[1].Value=Convert.ToInt32(dr[BaoXiaoPingZhengData.XUHAO_FIELD]);
searchParms[2].Value=dr[BaoXiaoPingZhengData.CODE_FIELD].ToString();
searchParms[3].Value=Convert.ToDecimal(dr[BaoXiaoPingZhengData.SUM_FIELD]);
odbc.ExecuteNonQuery(connstr,"insertYsqlBxMx",searchParms);
}

transaction.Commit();
conn.Close();
}
catch(Exception ex)
{
transaction.Rollback();
conn.Close();
throw ex;
}

这种情况,由于同样没有传入Transaction,事务回滚并没有执行,但是奇怪的是,这种情况没有报任何的错误。改正方法同1。

3.使用SqlCommandBuilder.DeriveParameters方法出现"当分配给命令的连接处于挂起的本地事务中时,命令必须具有事务对象才能执行。该命令的 Transaction 属性尚未初始化"。使用框架类库SqlClient命名空间下的类。来看一下错误的代码。

string connstr="server=localhost;database=XTERPCURBS;uid=sa;pwd=;";
SqlConnection conn=new SqlConnection(connstr);
conn.Open();
SqlTransaction tx = conn.BeginTransaction();
SqlCommand Comm = new SqlCommand();
Comm.CommandType = CommandType.StoredProcedure;
try
{
Comm.Connection = conn;
Comm.CommandText = "insertYsqlBxMx";
Comm.Transaction = tx;
SqlCommandBuilder.DeriveParameters(Comm);
tx.Commit();
}
catch(Exception ex)
{
tx.Rollback();
throw new Exception();
}

原因是SqlCommandBuilder.DeriveParameters方法不支持事务。可能有的读者会想到为什么DAAB 3.1的SqlServer类中ExecuteNonQuery(string connectionString, string spName, params object[] parameterValues)可以支持事务,我们来看一下SqlServer类的ExecuteNonQuery的代码,其中并没有用到 SqlCommandBuilder.DeriveParameters(IDbCommand cmd)方法而是使用了DAAB 3.1的类SqlDeriveParameters.DeriveParameters(IDbCommand cmd)。来看一下SqlDeriveParameters,DAAB 3.1创建这个类的解释是"We create our own class to do this because the existing ADO.NET 1.1 implementation is broken.",也就是说SqlCommandBuilder存在bug。对于Odbc的连接,DAAB 3.1仍然采用和SqlCommandBuilder类似的OdbcCommandBuilder。但我在测试中发现,OdbcCommandBuilder在Sql Server 2000下可以正常工作,而在Sybase 9.1.2下却无法取得存储过程的参数及其数据类型(参见我的另一篇文章使用DAAB 3.1连接Sybase ASE 11.9.2数据库的两个问题),对于事务没有测试,个人感觉应该能够支持。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐