和事务有关的几个问题 包含 com+ 事务 处理

using System;
using System.Collections.Generic;
using System.Text;

using System.Data;
using System.Data.Common;
using SQLServerDAL.Web.DbBooking;
using SQLServerDAL.Web.AppInterface;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Model.Web.DbBooking;


namespace SQLServerDAL.Web
{
public class DbTansactionHelper : SQLServerBase
{
private static readonly Database DbSupermaket = DatabaseFactory.CreateDatabase("GtaConnectionString");

public bool BookReseverTran(ContactInfo contactInfo, CustomerInfo customerInfo, BookHotelInfo bookHotelInfo, BookInfo bookInfo)
{
bool successFalg = true;
DbConnection gtaConn = db.CreateConnection();
DbConnection supermarketConn = DbSupermaket.CreateConnection();
try
{
gtaConn.Open();
DbTransaction gtaTtransaction = gtaConn.BeginTransaction();//事务与conn中的cmd有关,但必须在一个conn中
successFalg &= this.GtaBookTran(contactInfo, customerInfo, bookHotelInfo, bookInfo, gtaTtransaction);

supermarketConn.Open();
DbTransaction supermarketTtransaction = supermarketConn.BeginTransaction();
successFalg &= this.SupermarketReseverTran(supermarketTtransaction);

if (successFalg)
{
supermarketTtransaction.Commit();
gtaTtransaction.Commit(); //达到分布式的目的
}
else
{
supermarketTtransaction.Rollback();
gtaTtransaction.Rollback();
}
return successFalg;
}
finally
{
supermarketConn.Close();
gtaConn.Close();
}
}


public bool GtaBookTran(ContactInfo contactInfo, CustomerInfo customerInfo, BookHotelInfo bookHotelInfo, BookInfo bookInfo, DbTransaction transaction)
{
bool successFalg = true;
string hotelCustomeList;
string contactId;
string reseveId;
string hotelBookId;

Book book = new Book();
BookHotel bookHotel = new BookHotel();
Contact contact = new Contact();
Customer customer = new Customer();
//ReserveInterface reserveInterface = new ReserveInterface();

//插入到Contact表
successFalg &= contact.Insert(contactInfo, out contactId, transaction) > 0;

//插入到Customer表
successFalg &= customer.Insert(customerInfo, transaction) > 0;

//插入到BookHotel表
//传入时需初始化
//bookHotelInfo.Customer=hotelCustomeList
//successFalg &= bookHotel.Insert(bookHotelInfo, transaction) > 0;

//初始化Book总表
//bookInfo.BookId = bookId;
//bookInfo.ContactId = contactId;
//bookInfo.ReserveId = reseveId;
successFalg &= book.Insert(bookInfo, transaction)>0;
return successFalg;
}
public bool SupermarketReseverTran(DbTransaction transaction)
{
//插入到订单处理中心
//string webTypeAgentId = "cntocom";
//string webTypeDealer = "cxzhq2002";
//string webTypeMemberId = "cnto";
//LoginInfo loginInfo = new LoginInfo();
//string webTypeAgentId = loginInfo.AgentId;
//string webTypeDealer = loginInfo.Dealer;
//string webTypeMemberId = loginInfo.MemberId;
// successFalg = reserveInterface.ReserveHotel(bookInfo, bookHotelInfo, contactInfo, webTypeAgentId, webTypeDealer, webTypeMemberId, out reseveId);

//插入到Book总表
//bookInfo.ReserveId = reseveId;
//successFalg = book.Insert(bookInfo);
return true;
}
}
}

====================================

SqlTransaction与 DbTransaction事务

System.Object
<link keywords="T:System.MarshalByRefObject">
System.Data.Common.DbTransaction
System.Data.Odbc.OdbcTransaction
System.Data.OleDb.OleDbTransaction
System.Data.OracleClient.OracleTransaction
System.Data.SqlClient.SqlTransaction
System.Data.SqlServerCe.SqlCeTransaction

这是2.0的扩展类

在1.1中只实现了SqlTransaction.

代替类

bool successFalg = true;
using (TransactionScope insertTransaction = new TransactionScope())
{
string hotelCustomeList;
string contactId;
string reseveId;
string hotelBookId;

Book book = new Book();
BookHotel bookHotel = new BookHotel();
Contact contact = new Contact();
Customer customer = new Customer();
ReserveInterface reserveInterface = new ReserveInterface();

//插入到Contact表
ContactInfo contactInfo = this.InitContact();
successFalg &= contact.Insert(contactInfo, out contactId);

//插入到Customer表
ArrayList customerInfoList = this.InitCustomer(bookId, out hotelCustomeList);
successFalg &= customer.Insert(customerInfoList);

//插入到BookHotel表
BookHotelInfo bookHotelInfo = this.InitBookHotel(info, bookId, hotelCustomeList);
successFalg &= bookHotel.Insert(bookHotelInfo, out hotelBookId);

//初始化Book总表
BookInfo bookInfo = this.InitBook(bookId, hotelBookId, contactId, bookId, string.Empty);

//插入到订单处理中心
string webTypeAgentId = "cntocom";
string webTypeDealer = "cxzhq2002";
string webTypeMemberId = "cnto";
//LoginInfo loginInfo = new LoginInfo();
//string webTypeAgentId = loginInfo.AgentId;
//string webTypeDealer = loginInfo.Dealer;
//string webTypeMemberId = loginInfo.MemberId;
successFalg &= reserveInterface.ReserveHotel(bookInfo, bookHotelInfo, contactInfo, webTypeAgentId, webTypeDealer, webTypeMemberId, out reseveId);

//插入到Book总表
bookInfo.ReserveId = reseveId;
successFalg = book.Insert(bookInfo);

if (successFalg)
{
insertTransaction.Complete();
}
}
return successFalg;

System.Transactions 是借助的com+服务, 如果不行,则PlatformNotSupportedException。

,而DbTaansations是.net完全写的,性能应该好点

System.Transactions 基础结构既提供了基于 Transaction 类的显式编程模型,也提供了使用 TransactionScope 类的隐式编程模型,在后一种模型中,事务由该基础结构自动管理。

System.Transactions 基础结构通过支持在 SQL Server、ADO.NET、MSMQ 和 Microsoft 分布式事务协调器 (MSDTC) 中启动的事务,使事务编程在整个平台上变得简单和高效。它提供基于 Transaction 类的显式编程模型,还提供使用 TransactionScope 类的隐式编程模型,在这种模型中事务是由基础结构自动管理的。强烈建议使用更为方便的隐式模型进行开发。若要开始,请参见 <link keywords="1ddba95e-7587-48b2-8838-708c275e7199"> 主题。有关编写事务性应用程序的更多信息,请参见 <link keywords="d6debdf4-0502-4a27-bfc5-177318051084">。

相对于完全用.net实现有SqlTransaction与 DbTransaction事务, System.Transaction性能应该是差得,

但相关优化:另一个持久资源管理器向一个事务进行登记时,事务管理器还通过基于磁盘的事务管理器(如 DTC)进行协调,透明地将本地事务升级为分布式事务。System.Transactions 基础结构提供增强性能的关键方式有两种。

  • 动态升级,即 System.Transactions 基础结构只在事务实际需要 MSDTC 时才使用 MSDTC。这部分内容在 <link keywords="5b87ae58-8ccf-4b9b-9715-41e4aade89b7"> 主题中详细介绍。

  • 可升级登记,如果某个资源是参与事务的唯一实体,则允许该资源(如数据库)取得事务的所有权。以后,如果需要,System.Transactions 基础结构仍然可以将事务管理交给 MSDTC。这样进一步减少了使用 MSDTC 的机会。这部分内容在 <link keywords="653d51d1-b4bf-4e34-9a6f-aec073f0f5bb"> 主题中详细介绍。

==================================

以下转:

最近新搞了一台服务器,打算把sqlserver服务从我的机器上移出去,也让自己的机器轻松些,但在用到了事务处理时却出现了错误。
然后就是一顿搜索与设置,终于总结一部解决方案,如有不妥之处恳请指正。

经常出的错误主要有以下三条:
一、该伙伴事务管理器已经禁止了它对远程/网络事务的支持;
二、在分布式事务中登记时出错;
三、事务被明的或暗的终止。

通常这三条错误是有前后关系的,所以以下这些设置,可能要大多都要设置一次。

解决方案如下:
一、这个问题是因为你没有启用远程/网络事务。因为Win2003默认是不安装这个的。
安装步骤如下:
1. 单击“开始”,指向“控制面板”,然后单击“添加/删除程序”。
2. 单击“添加/删除 Windows 组件”。
3. 选择“应用程序服务器”,然后单击“详细信息”。
4. 选择“启用网络 DTC 访问”,然后单击“确定”。
5. 单击“下一步”。
6. 单击“完成”。
7. 停止分布式事务协调器服务:“Distributed Transaction Coordinator”,然后重新予以启动。
可以命令行执行:
net stop msdtc
net start msdtc
8. 停止参与分布式事务的任何资源管理器服务(如 Microsoft SQL Server 或 Microsoft Message Queue Server),然后重新予以启动。

二、
1、首先检查两台机器的msdtc是否都已经打开了。如是不是,那就全都打开。
2、按如下步骤做设置:

a.点击“开始”按钮,指向管理工具,选择"组件服务"。
b.展开"组件服务"树,然后展开"我的电脑"。
c.右键单击"我的电脑",然后选择"属性"。
d.在 MSDTC 选项卡中,点“安全配置”按钮,
e.确保选中了下列选项:“网络DTC访问”与"XA事务"
f.另外,"DTC 登录帐户"一定要设置为"NT Authority\NetworkService"。
3、单击"确定"。这样将会提示您"MS DTC 将会停止并重新启动。
所有的依赖服务将被停止。请按'是'继续"。单击"是"继续。
4、.单击"确定"关闭"我的电脑"属性窗口。
5、其他要说明的,在我的案例中没有这些设置,因为都已经满足了
打开135端口、SQLServer至少打到sp3的补丁,现在已经有sp4了、如果是WIN2000,升级到SP4、升级MDAC到2.6以上,最好是2.8。
三、这个步骤其实应该在第二.2步中设置的:
组件服务—我的电脑—右键—属性—MSDTC—安全配置—事务管理器通信不要求进行验证,启用XA事务
我用的是瑞星防火墙,要把安全级别设为中级,否则还是有问题。

最后强调,如果不行请检查两台机器的设置,不要只设置一台。
补充一点:有一次新装一台机器,按上面的步骤设置了一个遍,还是出现“在分布式事务中登记时出错”的错误,简直郁闷到了极点,后来将那台机器与 Sqlserver服务器放在同一个VLAN就一切OK了,原来是VLAN惹的祸,但是还是不明白为什么,可能是VLAN之间的路由规则过滤了什么,还希望有明白人指点一下呀!呵呵!

================================

假如分布式事务的客户端和服务器端(可能N个)不在同一台服务器上,如分别为 Web服务器 和 Db 服务器,可能会出现以下两个错误

1. 该伙伴事务管理器已经禁止了它对远程/网络事务的支持
通常这由安全配置引起的,对于 xp sp2/2k3+ ,默认可能关闭了远程客户端访问 MSDTC,
如何配置见网友 小小蚂蚱图文并茂的说明:
http://blog.csdn.net/bo310/archive/2007/08/30/1765728.aspx (找到最后一节“需要特别补充的是:”)
感谢 小小蚂蚱


2. [COMException (0x8004d00e): 此事务已明地或暗地被确认或终止 (异常来自 HRESULT:0x8004D00E)]

昨天刚解决的此问题:

在数据库服务器(MS SQL)上的 hosts 文件中加入 Web 服务器(IIS) 的 IP 和 主机名 映射对

a. 定位到 C:\WINDOWS\system32\drivers\etc 目录

b. 记事本打开 hosts 文件(没有扩展名)

c. 添加一行 Web 服务器 IP 和 主机名映射,两者以至少一个空格相隔,如

10.10.1.118MyWebServerHostName

d. Save,OK!

虽然问题,解决了,但是依然有疑惑:
为何我使用 IP 连接还需要映射 HostName?后面参考 分布式事务(一)——MTS设置中提到“如果Server之间跨网段,则Server之间需要能互相PING到机器名(而不是IP地址)”,但是我的环境的的确确就是同一个局域网啊?
为何 MSDTC 需要 HostName ?

此主题相关参考:
什么是 hosts ?它有什么作用?
http://baike.baidu.com/view/597330.htm

分布式事务(一)——MTS设置
http://blog.csdn.net/honkerhero/archive/2007/03/28/1544072.aspx

TransactionScope异常:该伙伴事务管理器已经禁止了它对远程/网络事务的支持
http://www.cnblogs.com/crabo/archive/2007/05/17/750118.html

http://topic.csdn.net/t/20050609/20/4071871.html
webservice实现com+事务出现"此事务已明地或暗地被确认或终止"问题

收到 " 一个 A Microsoft 分布式事务协调器问题阻止连接到配置数据库 " 发布程序集从 BizTalk Server 2004 时错误信息
http://support.microsoft.com/?kbid=839187

MSDTC 分布式事务错误:[COMException (0x8004d00e): 此事务已明地或暗地被确认或终止 (异常来自 HRESULT:0x8004D00E)]
http://community.csdn.net/Expert/TopicView3.asp?id=5748153

DTCPing.exe 工具
http://download.microsoft.com/download/complus/msdtc/1.7/nt45/en-us/DTCPing.exe

=================================

在一个MIS系统中,没有用事务那就绝对是有问题的,要么就只有一种情况:你的系统实在是太小了,业务业务逻辑有只要一步执行就可以完成了。因此掌握事务处理的方法是很重要,进我的归类在.net中大致有以下4种事务处理的方法。大家可以参考一下,根据实际选择适当的事务处理。
1 SQL事务
sql事务是使用SQL server自身的事务:在存储过程中直接使用Begin Tran,Rollback Tran,Commit Tran实现事务:
优点:执行效率最佳
限制:事务上下文仅在数据库中调用,难以实现复杂的业务逻辑。
Demo:(所有demo,都以SQL Server自带的Northwind数据的表Region为例)
带事务的存储过程
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->CREATEPROCEDUREdbo.SPTransaction
(
@UpdateIDint,
@UpdateValuenchar(50),
@InsertIDint,
@InsertValuenchar(50)
)
AS
beginTran
UpdateRegionSetRegionDescription=@UpdateValuewhereRegionID=@UpdateID

insertintoRegionValues(@InsertID,@InsertValue)

declare@RegionErrorint
select@RegionError=@@error
if(@RegionError=0)
COMMITTran
else
ROLLBACKTran
GO
执行带事务的存储过程
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->/**////<summary>
///SQL事务:
///</summary>

publicvoidSQLTran()
{
SqlConnectionconn
=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Northwind;PersistSecurityInfo=True;UserID=sa;Password=123;");
SqlCommandcmd
=newSqlCommand();
cmd.CommandText
="SPTransaction";
cmd.CommandType
=CommandType.StoredProcedure;
cmd.Connection
=conn;
conn.Open();
SqlParameter[]paras
=newSqlParameter[]{
newSqlParameter("@UpdateID",SqlDbType.Int,32),
newSqlParameter("@UpdateValue",SqlDbType.NChar,50),
newSqlParameter("@InsertID",SqlDbType.Int,32),
newSqlParameter("@InsertValue",SqlDbType.NChar,50)}
;
paras[
0].Value="2";
paras[
1].Value="UpdateValue1";
paras[
2].Value="6";
paras[
3].Value="InsertValue1";
foreach(SqlParameterparainparas)
{
cmd.Parameters.Add(para);
}

cmd.ExecuteNonQuery();
}

2 ADO.net事务
Ado.net事务可能是大家一般都用的
优点:简单,效率和数据库事务差不多。
缺点:事务不能跨数据库,只能在一个数据库连接上。如果是两个数据库上就不能使用该事务了。
Demo:
ADO.net事务
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->/**////<summary>
///一般的ADO.net事务
///</summary>

publicvoidADONetTran1()
{
SqlConnectionconn
=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Northwind;PersistSecurityInfo=True;UserID=sa;Password=123;");
SqlCommandcmd
=newSqlCommand();
try
{
cmd.CommandText
="UpdateRegionSetRegionDescription=@UpdateValuewhereRegionID=@UpdateID";
cmd.CommandType
=CommandType.Text;
cmd.Connection
=conn;
conn.Open();
SqlParameter[]paras
=newSqlParameter[]{
newSqlParameter("@UpdateID",SqlDbType.Int,32),
newSqlParameter("@UpdateValue",SqlDbType.NChar,50)}
;
paras[
0].Value="2";
paras[
1].Value="UpdateValue12";

foreach(SqlParameterparainparas)
{
cmd.Parameters.Add(para);
}

//开始事务
cmd.Transaction=conn.BeginTransaction();
cmd.ExecuteNonQuery();


cmd.CommandText
="insertintoRegionvalues(@InsertID,@InsertValue)";
cmd.CommandType
=CommandType.Text;

paras
=newSqlParameter[]{
newSqlParameter("@InsertID",SqlDbType.Int,32),
newSqlParameter("@InsertValue",SqlDbType.NChar,50)}
;
paras[
0].Value="7";
paras[
1].Value="InsertValue";

cmd.Parameters.Clear();
foreach(SqlParameterparainparas)
{
cmd.Parameters.Add(para);
}


cmd.ExecuteNonQuery();
//提交事务
cmd.Transaction.Commit();
}

catch
{
//回滚事务
cmd.Transaction.Rollback();
throw;
}

finally
{
conn.Close();
}


}
3 TransactionScope事务
TransactionScope事务类,它可以使代码块成为事务性代码。并自动提升为分布式事务
优点:实现简单,同时能够自动提升为分布式事务
Demo:
TransactionScope事务
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->/**////<summary>
///TransactionScope事务:可自动提升事务为完全分布式事务的轻型(本地)事务。
///使用时要保证MSDTC服务(控制分布事务)是开启的可以使用:netstartmsdtc命令开启服务;
///</summary>

publicvoidADONetTran2()
{
SqlConnectionconn
=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Northwind;PersistSecurityInfo=True;UserID=sa;Password=123;");
SqlCommandcmd
=newSqlCommand();
try
{

using(System.Transactions.TransactionScopets=newTransactionScope())
{

cmd.CommandText
="UpdateRegionSetRegionDescription=@UpdateValuewhereRegionID=@UpdateID";
cm
分享到:
评论

你可能感兴趣的:(sql,编程,应用服务器,server,配置管理,asp.net)