Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 应用层消除SQL事务错误_C#_Sql_Sql Server_Asp.net Mvc - Fatal编程技术网

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将其设置为零。这是最基本的事情之一。