【问题标题】:Pitfalls of using SQL transactions vs .NET transactions使用 SQL 事务与 .NET 事务的陷阱
【发布时间】:2013-08-12 17:18:15
【问题描述】:

我一直在尝试在 SQL Server 和 C# 中使用事务。考虑一个在三列表中插入一行的存储过程

alter proc spInsertItem
 @itemId int
,@itemDescription varchar(50)
,@itemCost decimal
as
begin
    if(@itemCost < 0)
        begin
            raiserror('cost cannot be less than 0',16,1)
        end

    else
        begin
            begin try
                begin tran
                    insert into Items(itemid, [description],itemCost)
                    values (@itemid, @itemdescription,@itemCost)
                commit tran
            end try
        begin catch
            rollback tran
                select   ERROR_LINE()as errorLine
                        ,ERROR_MESSAGE() as errorMessage
                        ,ERROR_STATE() as errorState
                        ,ERROR_PROCEDURE() as errorProcedure
                        ,ERROR_NUMBER() as errorNumber
        end catch
    end
end 

对比

create proc spInsertItem2
 @itemid int
,@itemDescription varchar(50)
,@itemCost decimal
as
begin
insert into Items(ItemId,[Description],ItemCost)
values (@itemid, @itemDescription,@itemCost)
end

在第一个示例中,用户被告知他们无法输入低于 0 的项目成本,其余部分非常不言自明。这让我想到,如果你要禁止某些值,你应该需要一个检查约束,所以我添加了以下约束

alter table items
add constraint chkItemCost 
check (ItemCost > 0)

现在这两个存储过程在代码中的功能相同,并且 SQL 更短,在我看来,在第二个更短的版本中更易于阅读。当然,这是一个非常基本的示例,但在我看来,如果您在调用存储过程时在代码中看到 try/catch,则可以确定数据库没有处于不一致状态。那么,我错过了什么不应该依赖 C# 来创建事务?

【问题讨论】:

  • 仅供参考 - 编辑您的标题,因为您的真正意思是“.NET Transactions”
  • 真正的用例是更长的过程,特别是如果您需要使用显式事务(即从表中删除记录然后插入新数据) - 您希望 try/catch 中止过程然后在 catch 中添加回滚。
  • @JNK 所以对于较小的“日常”类型的应用程序,即典型的更新、插入、删除,可能不需要在 SQL 中编写事务?
  • @JohnSaunders 正确,谢谢。
  • @wootscootinboogie 这取决于您是否打算从 .NET 代码之外的任何地方调用这些 proc。如果你这样做,那么我认为事务应该在 SQL 中,但我是 SQL 开发人员,所以我有偏见

标签: c# sql transactions


【解决方案1】:

这通常是一个设计决定;应用程序的逻辑所在的位置。如果您决定将业务逻辑集中在应用程序代码中,对于涉及多次访问数据库的每个原子应用程序逻辑,您需要使用 C# 中的事务来包装该逻辑。

然而,如果您在 SP 的帮助下将业务逻辑存放在数据库中,则不需要 C# 中的事务。

一个常见的场景是:

  1. 您在数据库中创建了一条或多条记录。
  2. 您在 C# 中对此数据进行了一些后期处理。
  3. 您使用刚刚处理的数据更新另一个表。

要求是,如果第 2 步或第 3 步失败,则应回滚第 1 步(创建的记录)。为此,您需要交易。您可能会争辩说,您可以将所有三个步骤都放在一个 SP 中并用事务包装它;这应该是可能的,通常是您将应用程序逻辑放在哪里的偏好问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多