更新:我找到了一篇文章,解释了为什么在TransactionScope中仅使用GetData和Update来自同一个数据适配器时,事务会从LTM升级到MSDTC,并提供了一种解决方法。
关于TableAdapters + Transactions的权威博客文章
http://blah.winsmarts.com/2006/06/18/the-definitive-tableadapters--transactions-blog-post.aspx
我理解同时打开多个连接会导致事务分布式升级。然而,我遇到了一个问题,只有一个连接和一个针对数据库的查询也会导致事务升级。存储过程中也没有任何事务。如果有人知道原因,请告诉我。根据我的代码示例,“adapter.Update(table)”将触发分布式事务。
我已经将代码的核心从现有项目中提取出来并简化了大部分操作,但仍然遇到同样的问题。这基本上是使用表适配器创建数据集,并使用存储过程进行选择、插入和删除。我选择所有与特定用户相关的记录。然后,根据记录中是否存在“myPPID”,我添加或删除它。然后调用更新方法,并通过在组件服务中观察事务统计信息来看到事务升级为分布式。
我正在使用Windows XP Pro SP3和.NET Framework 3.5作为客户端程序。它通过局域网连接到SQL 2005数据库,该数据库位于Windows Server 2003 R2 Enterprise Edition SP2上。
private void button1_Click(object sender, EventArgs e)
{
int userId = 3;
int myPPId = 881;
using (TransactionScope ts = new TransactionScope())
{
using (DataSet1TableAdapters.AssignedPPTableAdapter adapter
= new MSDTCPromotionTest.DataSet1TableAdapters.AssignedPPTableAdapter())
{
using (DataSet1.AssignedPPDataTable table = adapter.GetData(userId))
{
DataSet1.AssignedPPRow row = table.FindByUserIdmyPPId(
userId, myPPId);
if (row == null)
{
table.AddAssignedPPRow(userId, myPPId, string.Empty,
string.Empty, true);
}
else
{
row.Delete();
}
adapter.Update(table);
}
ts.Complete();
}
}
}
连接字符串并没有什么特别之处:
<add name="ConnectionString" connectionString="
Data Source=devdb;
Initial Catalog="TEST MSDTC";
Integrated Security=True"
providerName="System.Data.SqlClient" />
此外,存储过程是简单的CRUD调用。
创建:
ALTER procedure [dbo].[p_UserForm_AssignedPP_Insert]
(
@UserId INT,
@myPPId int
)
AS
SET NOCOUNT ON;
INSERT INTO [UsermyPP] ([UserID],[myPPID],[DateCreated])
VALUES (@UserId,@myPPId,GETutcDATE())
阅读:
ALTER procedure [dbo].[p_UserForm_AssignedPP_SelectByUserId]
(
@UserId int
)
AS
SELECT
[UserId],
[myPPId],
'' Title,
'' Abbreviation,
0 IsArchived
from
UsermyPP unpp
where
unpp.[userid] = @UserId
删除:
ALTER procedure [dbo].[p_UserForm_AssignedPP_Delete]
(
@Original_UserId INT,
@Original_MyPPId INT
)
AS
SET NOCOUNT ON;
DELETE FROM usermypp WHERE [UserID] = @Original_UserId
AND [MyPPID] = @Original_MyPPId