使用SQL事务与.NET事务的陷阱

时间:2013-08-12 17:18:16

标签: c# sql transactions

我一直在使用SQL服务器和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 

vs

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#来创建交易?

1 个答案:

答案 0 :(得分:0)

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

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

常见的情况是:

  1. 您在数据库中创建一个或多个记录。
  2. 您可以使用C#对此数据进行一些后期处理。
  3. 您使用刚刚处理的数据更新另一个表。
  4. 要求是如果步骤2或3失败,则应回滚步骤1(创建的记录)。为此你需要交易。您可能会争辩说,您可以将所有三个步骤放在SP中并用事务包装它;它应该是可能的,并且通常是您放置应用程序逻辑的首选项。

相关问题