我一直在使用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#来创建交易?
答案 0 :(得分:0)
这通常是一个设计决定;应用程序逻辑所在的位置。如果您决定将业务逻辑集中在应用程序代码中,对于涉及多次访问数据库的每个原子应用程序逻辑,您需要使用C#中的事务来包装该逻辑。
然而,如果您在SP的帮助下在数据库中存放业务逻辑,则不需要在C#中进行事务处理。
常见的情况是:
要求是如果步骤2或3失败,则应回滚步骤1(创建的记录)。为此你需要交易。您可能会争辩说,您可以将所有三个步骤放在SP中并用事务包装它;它应该是可能的,并且通常是您放置应用程序逻辑的首选项。