C# 应用层消除SQL事务错误
我有一个存储过程C# 应用层消除SQL事务错误,c#,sql,sql-server,asp.net-mvc,C#,Sql,Sql Server,Asp.net Mvc,我有一个存储过程 create proc spInsertRole @rolename varchar(50) as begin set nocount on begin try begin tran if len(@roleName) > 15 Raiserror('Role name is too long',1,5) insert into webpages_Roles(RoleName)
create proc spInsertRole
@rolename varchar(50)
as
begin
set nocount on
begin try
begin tran
if len(@roleName) > 15
Raiserror('Role name is too long',1,5)
insert into webpages_Roles(RoleName)
values (@roleName)
commit tran
end try
begin catch
select ERROR_MESSAGE() as ErrorMessage
rollback tran
end catch
end
如果我在SSMS中,并且我尝试添加一个长度超过15个字符的角色,则此代码将阻止这种情况发生,并向我提供一条错误消息“角色名称太长”
当我使用下面的C时,这段代码将允许将记录添加到数据库中。我需要知道为什么C SqlTransaction会取代SQL Server事务,以及在C代码中检查roleName.Length>15的位置,以向用户显示一个错误,即MVC应用程序中的角色名称太长
public void InsertRole(string roleName)
{
using (var con = new SqlConnection(cs))
{
con.Open();
SqlTransaction transaction;
transaction = con.BeginTransaction();
SqlCommand command = new SqlCommand("spInsertRole", con, transaction);
try
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@roleName", roleName);
command.ExecuteNonQuery();
transaction.Commit();
}
//how to throw this to the UI in MVC?
catch (Exception ex)
{
try
{
transaction.Rollback();
}
catch (Exception rollBackException)
{
throw;
}
}
}
}
您正在使用严重性为1的RAISERROR,但严重性为10或更低不会将控制转移到CATCH块,它只是打印错误消息。使用更高的严重性 比较以下代码:
declare @rolename varchar(50) = '123456789123456789'
begin try
begin tran
if len(@roleName) > 15
Raiserror('Role name is too long',1,5)
print 'inserting...'
insert into webpages_Roles(RoleName)
values (@roleName)
print 'committing...'
commit tran
end try
begin catch
print 'catch'
select ERROR_MESSAGE() as ErrorMessage
print 'rolling back...'
rollback tran
end catch
关于这一点:
declare @rolename varchar(50) = '123456789123456789'
begin try
begin tran
if len(@roleName) > 15
Raiserror('Role name is too long',11,5)
print 'inserting...'
insert into webpages_Roles(RoleName)
values (@roleName)
print 'committing...'
commit tran
end try
begin catch
print 'catch'
select ERROR_MESSAGE() as ErrorMessage
print 'rolling back...'
rollback tran
end catch
第一个使用严重度1,并且控件未转移到CATCH块;另一个使用严重性为11的验证,并最终进入CATCH。您应该在应用程序层而不是SQL中保持这种验证。另一件事是,因为您在插入之前的最后一步实现了这个检入,所以您允许错误的值通过多个层。例如,您使用VARCHAR50定义了SP参数。理想情况下,当用户输入角色名称时,仅在客户端,您应该检查长度。@AnupShah我也希望保留服务器端验证,以防禁用JavaScript。您不应该在应用程序代码和存储过程中同时使用事务。因为@trancount在使用这两种代码时很可能无法正确递增/递减,在应用程序代码的回滚过程中会导致许多问题。实际上,它是非常协调地更新的:BEGINT tran递增1,commit递减1,rollback将其设置为零。这是最基本的事情之一。