[原创]谈谈基于SQL Server 的Exception Handling-PART2
点击次数:19 次 发布日期:2008-11-26 10:33:41 作者:源代码网
|
源代码网推荐 在上面一节中,我通过RAISERROR重写了创建User的Stored procedure,实际上上面的Stored procedure是有问题的。我之所以没有立即指出,是因为这是一个很容易犯的错误,尤其是习惯了.NET Exception Handling的人更容易犯这样的错误。我们知道在.NET Application中,如果出现一个未处理的Exception,程序将立即终止,后续的程序将不会执行,但是对于上面的SQL则不一样,虽然我们通过RAISERROR将Error抛出,但是SQL的指定并不会被终止,INSERT语句仍然会被执行的。我想很多人会说在RAISERROR后加一个Return就可以了嘛。不错这是一个常用的解决方案,但是我不倾向于使用这种方法。为了更清楚地说明这个问题,我们举另一个相关的例子,上面我们介绍了创建User的例子,我们现在来引入另一个例子:如何将一个User添加到一个Role里面。由于这个例子在后面还将使用,我先讲设计的Table的结构介绍一下:T_USERS和T_ROLES分别存放User和Role,User和Role不区分大小写并且唯一,两者通过T_USERS_IN_ROLES进行关联。 源代码网推荐 源代码网推荐 现在我们来写将user添加到Role的Stored Procedure:首先验证User和Role是否存在,然后验证该User和Role是否已经存在,最后将Mapping关系添加到T_USERS_IN_ROLES中: 源代码网推荐 源代码网推荐 CREATE Procedure P_USERS_IN_ROLES_I 源代码网推荐 ( 源代码网推荐 @user_name NVARCHAR(256), 源代码网推荐 @role_name NVARCHAR(256) 源代码网推荐 ) 源代码网推荐 AS 源代码网推荐 DECLARE @user_id VARCHAR(50) 源代码网推荐 DECLARE @role_id VARCHAR(50) 源代码网推荐 SELECT @user_id = [USER_ID] FROM dbo.T_USERS WHERE LOWERED_USER_NAME = LOWER(@user_name) 源代码网推荐 IF(@user_id IS NULL) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR ("The user dose not exist",16,1) 源代码网推荐 RETURN 源代码网推荐 END 源代码网推荐 源代码网推荐 SELECT @role_id = [ROLE_ID] FROM dbo.T_ROLES WHERE LOWERED_ROLE_NAME = LOWER(@role_name) 源代码网推荐 IF(@role_id IS NULL) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR ("The role dose not exist",16,1) 源代码网推荐 RETURN 源代码网推荐 END 源代码网推荐 IF(EXISTS(SELECT * FROM T_USERS_IN_ROLES WHERE [USER_ID] = @user_id AND ROLE_ID = @role_id)) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR ("The user is already in the role",16,1) 源代码网推荐 RETURN 源代码网推荐 END 源代码网推荐 INSERT INTO dbo.T_USERS_IN_ROLES([USER_ID],ROLE_ID) VALUES(@user_id,@role_id) 源代码网推荐 源代码网推荐 源代码网推荐 虽然说在上面的Stored procedure中,我们在困难出现Exception的地方添加了RETURN,从而防止了后续的程序继续执行,但是对于一些我们无法预知的Exception呢?我们该如何添加这个RETURN呢?我想有人会说在每条语句执行之后都通过@@ERROR判断是否有Exception出现,我知道很多人喜欢这么做,而事实上,我现在真在维护的一些Stored procedure就是这么做的:全篇都是IF@@ERROR RETURN。其实我们完全可以通过其它的方式是我们的SQL看出来更加优雅一点。那就是使用我们很熟悉的TRY CATCH。在SQL Server中我们通过BEGIN TRY/END TRY和BEGIN CATCH/END CATCH这样的结构来进行Exception Handling。 源代码网推荐 源代码网推荐 通过TRY CATCH,上面的Stored procedure可以改成下面的样子: 源代码网推荐 源代码网推荐 CREATE Procedure P_USERS_IN_ROLES_I 源代码网推荐 ( 源代码网推荐 @user_name NVARCHAR(256), 源代码网推荐 @role_name NVARCHAR(256) 源代码网推荐 ) 源代码网推荐 AS 源代码网推荐 DECLARE @user_id VARCHAR(50) 源代码网推荐 DECLARE @role_id VARCHAR(50) 源代码网推荐 源代码网推荐 DECLARE @error_message NVARCHAR(256) 源代码网推荐 DECLARE @error_serverity INT 源代码网推荐 DECLARE @error_state INT 源代码网推荐 源代码网推荐 BEGIN TRY 源代码网推荐 源代码网推荐 SELECT @user_id = [USER_ID] FROM dbo.T_USERS WHERE LOWERED_USER_NAME = LOWER(@user_name) 源代码网推荐 IF(@user_id IS NULL) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR ("The user dose not exist",16,1) 源代码网推荐 END 源代码网推荐 源代码网推荐 SELECT @role_id = [ROLE_ID] FROM dbo.T_ROLES WHERE LOWERED_ROLE_NAME = LOWER(@role_name) 源代码网推荐 IF(@role_id IS NULL) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR ("The role dose not exist",16,1) 源代码网推荐 END 源代码网推荐 IF(EXISTS(SELECT * FROM T_USERS_IN_ROLES WHERE [USER_ID] = @user_id AND ROLE_ID = @role_id)) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR ("The user is already in the role",16,1) 源代码网推荐 END 源代码网推荐 INSERT INTO dbo.T_USERS_IN_ROLES([USER_ID],ROLE_ID) VALUES(@user_id,@role_id) 源代码网推荐 源代码网推荐 END TRY 源代码网推荐 源代码网推荐 BEGIN CATCH 源代码网推荐 源代码网推荐 SET @error_ message = ERROR_MESSAGE) 源代码网推荐 SET @error_serverity = ERROR_SEVERITY() 源代码网推荐 SET @error_state = ERROR_STATE() 源代码网推荐 RAISERROR(@error_message,@error_serverity,@error_state) 源代码网推荐 源代码网推荐 END CATCh 源代码网推荐 源代码网推荐 当执行上面一个SQL的时候,碰到任何一个我们自己抛出的Exception和系统异常,都会跳到Catch Block中执行相应的操作。在CATCH中,我们把在TRY Block中遇到的Error从新抛出。 源代码网推荐 源代码网推荐 在这里有一些需要注意的是:并非所有的Error都会使用SQL的执行流入Catch Block,下面是两个主要的例外: 源代码网推荐 源代码网推荐 Severity<10 源代码网推荐 Severity>20并且会马上中止Session 源代码网推荐 此外,相信大家也看见了在Catch中使用了一些Error作为前缀的Function,这些Function为系统定义的Function,用于返回当前Error的一些信息,这样的Function有: 源代码网推荐 源代码网推荐 ERROR_NUMBER():返回Error Number,相当于@@ERROR。 源代码网推荐 ERROR_MESSAGE():返回Error message. 源代码网推荐 ERROR_SEVERITY():返回Error严重级别. 源代码网推荐 ERROR_STATE() :返回Error的状态. 源代码网推荐 ERROR_LINE() :返回出现Error的行号. 源代码网推荐 ERROR_PROCEDURE() :返回出现Error的Stored Procedure名称. 源代码网推荐 四、 Error message & sys.messages 源代码网推荐 从前面的部分我们可以主要介绍了一种基于RAISERROR和TRY/CATCH的异常处理机制,个人觉得这是一种值得推荐的做法。但是上面的处理有一种不太理想的做法是:在每个Stored procedure中为不同的Error定义了Message。其实在很多情况下,每个Stored procedure都需要处理一些共同的Error,而且对于.NET Application来说往往是通过Message来判断Exception的类型,所以保持各个Stored Procedure的Message的一致性和Stored procedure和Application的Message的一致性就显得尤为重要。所以我们希望的做法是一次定义,对此使用。在Oracle中,我们知道我们可以通过定义具有全局意义的常数来解决,而对于SQL Server,没有全局常数的概念(在我的印象中好像没有),我们需要寻求另一种解决方案:将Message 添加到sys.messages中。 源代码网推荐 源代码网推荐 在前面的部分我们说过,sys.messages是可以用于专门存放Error相关的信息:Error number, severity,state,message等。而且他不但可以用于系统与定义error的存储,也可以用于存放我们自定义的Error。更加可喜的是,SQL Server定义了一些built-in stored procedure来用于message的添加、删除和修改: 源代码网推荐 源代码网推荐 sp_addmessage [ @msgnum = ] msg_id , [ @severity = ] severity , [ @msgtext = ] "msg" 源代码网推荐 [ , [ @lang = ] "language" ] 源代码网推荐 [ , [ @with_log = ] "with_log" ] 源代码网推荐 [ , [ @replace = ] "replace" ] 源代码网推荐 源代码网推荐 sp_dropmessage [ @msgnum = ] message_number [ , [ @lang = ] "language" ] 源代码网推荐 sp_altermessage [ @message_id = ] message_number , [ @parameter = ] "write_to_log" , [ @parameter_value = ] "value" 源代码网推荐 关于如何使用这些stored procedure,可以参阅SQL Server Books Online。在这里,我同下面的script添加我需要的Error。 源代码网推荐 源代码网推荐 源代码网推荐 sp_addmessage @msgnum = 50001,@severity = 16,@msgtext = N"This user is already existent" , @replace = "replace" 源代码网推荐 GO 源代码网推荐 sp_addmessage @msgnum = 50002,@severity = 16,@msgtext = N"This role is already existent", @replace = "replace" 源代码网推荐 Go 源代码网推荐 sp_addmessage @msgnum = 50003,@severity = 16,@msgtext = N"This user does not exist", @replace = "replace" 源代码网推荐 GO 源代码网推荐 sp_addmessage @msgnum = 50004,@severity = 16,@msgtext = N"This role does not exist", @replace = "replace" 源代码网推荐 GO 源代码网推荐 sp_addmessage @msgnum = 50005,@severity = 16,@msgtext = N"This user is already in the role", @replace = "replace" 源代码网推荐 GO 源代码网推荐 源代码网推荐 [注:直接操作sys.messages是不被允许的] 源代码网推荐 源代码网推荐 五、 ADO.NET Exception Handling 源代码网推荐 上面所有的都在介绍在Database层面如何进行Exception handling,下面我们同一个简单的Demo,简单介绍一个我么的.NET Application如何处理从Database Engine抛出的Exception。在这里我们使用一个简单的Cosole application模拟一个简单的Security方面的场景:创建用户、创建角色、添加用户到角色。大部分的功能都在上面提到了,在这里做一下总结: 源代码网推荐 源代码网推荐 2. Messages(通过上面一节末Script在sys.messages中创建): 源代码网推荐 · 50001:This user is already existent 源代码网推荐 · 50002:This role is already existent 源代码网推荐 · 50003:This user does not exist 源代码网推荐 · 50004:This role does not exist 源代码网推荐 · 50005:This user is already in the role 源代码网推荐 源代码网推荐 3. Stored procedure 源代码网推荐 · Create User:P_USERS_I 源代码网推荐 源代码网推荐 源代码网推荐 CREATE Procedure P_USERS_I 源代码网推荐 ( 源代码网推荐 @user_id varchar(50), 源代码网推荐 @user_name nvarchar(256) 源代码网推荐 ) 源代码网推荐 AS 源代码网推荐 源代码网推荐 DECLARE @error_number INT 源代码网推荐 DECLARE @error_serverity INT 源代码网推荐 DECLARE @error_state INT 源代码网推荐 源代码网推荐 BEGIN TRY 源代码网推荐 源代码网推荐 IF(EXISTS(SELECT * FROM dbo.T_USERS WHERE LOWERED_USER_NAME = LOWER(@user_name) OR [USER_ID] = @user_id)) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR (50001,16,1) 源代码网推荐 END 源代码网推荐 源代码网推荐 INSERT INTO dbo.T_USERS 源代码网推荐 ([USER_ID] 源代码网推荐 ,[USER_NAME] 源代码网推荐 ,LOWERED_USER_NAME) 源代码网推荐 VALUES(@user_id, @user_name, LOWER(@user_name)) 源代码网推荐 源代码网推荐 END TRY 源代码网推荐 源代码网推荐 BEGIN CATCH 源代码网推荐 源代码网推荐 SET @error_number = ERROR_NUMBER() 源代码网推荐 SET @error_serverity =ERROR_SEVERITY() 源代码网推荐 SET @error_state = ERROR_STATE() 源代码网推荐 RAISERROR(@error_number,@error_serverity,@error_state) 源代码网推荐 源代码网推荐 END CATCH 源代码网推荐 源代码网推荐 · Create Role:T_ROLES_I 源代码网推荐 源代码网推荐 CREATE Procedure T_ROLES_I 源代码网推荐 ( 源代码网推荐 @role_id varchar(50), 源代码网推荐 @role_name nvarchar(256) 源代码网推荐 ) 源代码网推荐 AS 源代码网推荐 源代码网推荐 DECLARE @error_number INT 源代码网推荐 DECLARE @error_serverity INT 源代码网推荐 DECLARE @error_state INT 源代码网推荐 源代码网推荐 BEGIN TRY 源代码网推荐 源代码网推荐 IF(EXISTS(SELECT * FROM dbo.T_ROLES WHERE LOWERED_ROLE_NAME = LOWER(@ROLE_name) OR [ROLE_ID] = @role_id)) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR (50002,16,1) 源代码网推荐 END 源代码网推荐 源代码网推荐 INSERT INTO dbo.T_ROLES 源代码网推荐 ([ROLE_ID] 源代码网推荐 ,[ROLE_NAME] 源代码网推荐 ,LOWERED_ROLE_NAME) 源代码网推荐 VALUES(@ROLE_id, @ROLE_name, LOWER(@ROLE_name)) 源代码网推荐 源代码网推荐 END TRY 源代码网推荐 源代码网推荐 BEGIN CATCH 源代码网推荐 源代码网推荐 SET @error_number = ERROR_NUMBER() 源代码网推荐 SET @error_serverity =ERROR_SEVERITY() 源代码网推荐 SET @error_state = ERROR_STATE() 源代码网推荐 RAISERROR(@error_number,@error_serverity,@error_state) 源代码网推荐 END CATCH 源代码网推荐 源代码网推荐 · Add User in Role:P_USERS_IN_ROLES_I 源代码网推荐 源代码网推荐 CREATE Procedure P_USERS_IN_ROLES_I 源代码网推荐 ( 源代码网推荐 @user_name NVARCHAR(256), 源代码网推荐 @role_name NVARCHAR(256) 源代码网推荐 ) 源代码网推荐 AS 源代码网推荐 源代码网推荐 DECLARE @user_id VARCHAR(50) 源代码网推荐 DECLARE @role_id VARCHAR(50) 源代码网推荐 源代码网推荐 DECLARE @error_number INT 源代码网推荐 DECLARE @error_serverity INT 源代码网推荐 DECLARE @error_state INT 源代码网推荐 源代码网推荐 BEGIN TRY 源代码网推荐 源代码网推荐 SELECT @user_id = [USER_ID] FROM dbo.T_USERS WHERE LOWERED_USER_NAME = LOWER(@user_name) 源代码网推荐 源代码网推荐 IF(@user_id IS NULL) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR (50003,16,1) 源代码网推荐 END 源代码网推荐 源代码网推荐 SELECT @role_id = [ROLE_ID] FROM dbo.T_ROLES WHERE LOWERED_ROLE_NAME = LOWER(@role_name) 源代码网推荐 源代码网推荐 IF(@role_id IS NULL) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR (50004,16,1) 源代码网推荐 END 源代码网推荐 源代码网推荐 IF(EXISTS(SELECT * FROM T_USERS_IN_ROLES WHERE [USER_ID] = @user_id AND ROLE_ID = @role_id)) 源代码网推荐 BEGIN 源代码网推荐 RAISERROR (50005,16,1) 源代码网推荐 END 源代码网推荐 源代码网推荐 INSERT INTO dbo.T_USERS_IN_ROLES([USER_ID],ROLE_ID) VALUES(@user_id,@role_id) 源代码网推荐 源代码网推荐 END TRY 源代码网推荐 源代码网推荐 BEGIN CATCH 源代码网推荐 源代码网推荐 SET @error_number = ERROR_NUMBER() 源代码网推荐 SET @error_serverity =ERROR_SEVERITY() 源代码网推荐 SET @error_state = ERROR_STATE() 源代码网推荐 RAISERROR(@error_number,@error_serverity,@error_state) 源代码网推荐 END CATCH 源代码网推荐 源代码网推荐 · Delete Data: P_CLEAR_DATA 源代码网推荐 源代码网推荐 CREATE Procedure P_CLEAR_DATA 源代码网推荐 AS 源代码网推荐 源代码网推荐 DELETE FROM dbo.T_USERS_IN_ROLES 源代码网推荐 DELETE FROM dbo.T_USERS 源代码网推荐 DELETE FROM dbo.T_ROLES 源代码网推荐 源代码网推荐 GO 源代码网推荐 源代码网推荐 4. Common Function:Utility. ExecuteCommand 源代码网推荐 源代码网推荐 源代码网推荐 源代码网推荐 private const string connectionStringName = "TestDb"; 源代码网推荐 public static bool ExecuteCommand(string procedureName, Dictionary<string, object> parameters) 源代码网推荐 { 源代码网推荐 ConnectionStringSettings connectionStringSection = ConfigurationManager.ConnectionStrings[connectionStringName]; 源代码网推荐 DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory(connectionStringSection.ProviderName); 源代码网推荐 using (DbConnection connection = dbProviderFactory.CreateConnection()) 源代码网推荐 { 源代码网推荐 connection.ConnectionString = connectionStringSection.ConnectionString; 源代码网推荐 connection.Open(); 源代码网推荐 DbCommand command = connection.CreateCommand(); 源代码网推荐 command.CommandText = procedureName; 源代码网推荐 command.CommandType = CommandType.StoredProcedure; 源代码网推荐 DbParameter parameter; 源代码网推荐 foreach (KeyValuePair<string, object> param in parameters) 源代码网推荐 { 源代码网推荐 parameter = dbProviderFactory.CreateParameter(); 源代码网推荐 parameter.ParameterName = param.Key; 源代码网推荐 parameter.DbType = DbType.String; 源代码网推荐 parameter.Value = param.Value; 源代码网推荐 command.Parameters.Add(parameter); 源代码网推荐 } 源代码网推荐 DbTransaction transation = connection.BeginTransaction(); 源代码网推荐 command.Transaction = transation; 源代码网推荐 try 源代码网推荐 { 源代码网推荐 command.ExecuteNonQuery(); 源代码网推荐 transation.Commit(); 源代码网推荐 return true; 源代码网推荐 } 源代码网推荐 catch 源代码网推荐 { 源代码网推荐 transation.Rollback(); 源代码网推荐 throw; 源代码网推荐 } 源代码网推荐 } 源代码网推荐 } 源代码网推荐 源代码网推荐 源代码网推荐 源代码网推荐 源代码网推荐 5. Create User, Create Role, Add User In Role, Delete All Data 源代码网推荐 源代码网推荐 源代码网推荐 private const string ErrorUserExists = "This user is already existent"; 源代码网推荐 private const string ErrorRoleExists = "This role is already existent"; 源代码网推荐 private const string ErrorUserNotExists = "This user does not exist"; 源代码网推荐 private const string ErrorRoleNotExists = "This role does not exist"; 源代码网推荐 private const string ErrorUserInRole = "This user is already in the role"; 源代码网推荐 源代码网推荐 public static bool CreateUser(string userName) 源代码网推荐 { 源代码网推荐 string procedureName = "P_USERS_I"; 源代码网推荐 Dictionary<string, object> parameters = new Dictionary<string, object>(); 源代码网推荐 parameters.Add("user_id", Guid.NewGuid().ToString()); 源代码网推荐 parameters.Add("user_name", userName); 源代码网推荐 try 源代码网推荐 { 源代码网推荐 ExecuteCommand(procedureName, parameters); 源代码网推荐 return true; 源代码网推荐 } 源代码网推荐 catch (Exception ex) 源代码网推荐 { 源代码网推荐 if (ex.Message == ErrorUserExists) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The user "{0}" you specify is already existent!",userName); 源代码网推荐 return false; ; 源代码网推荐 } 源代码网推荐 Console.WriteLine("A unhandled exception is thrown for some unknown reason!"); 源代码网推荐 return false; 源代码网推荐 } 源代码网推荐 } 源代码网推荐 源代码网推荐 public static bool CreateRole(string roleName) 源代码网推荐 { 源代码网推荐 string procedureName = "P_ROLES_I"; 源代码网推荐 Dictionary<string, object> parameters = new Dictionary<string, object>(); 源代码网推荐 parameters.Add("role_id", Guid.NewGuid().ToString()); 源代码网推荐 parameters.Add("role_name", roleName); 源代码网推荐 try 源代码网推荐 { 源代码网推荐 ExecuteCommand(procedureName, parameters); 源代码网推荐 return true; 源代码网推荐 } 源代码网推荐 catch (Exception ex) 源代码网推荐 { 源代码网推荐 if (ex.Message==ErrorRoleExists) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The role "{0}" you specify is already existent!",roleName); 源代码网推荐 return false; ; 源代码网推荐 } 源代码网推荐 Console.WriteLine("A unhandled exception is thrown for some unknown reason!"); 源代码网推荐 return false; 源代码网推荐 } 源代码网推荐 } 源代码网推荐 源代码网推荐 public static bool AddUserInRole(string userName, string roleName) 源代码网推荐 { 源代码网推荐 string procedureName = "P_USERS_IN_ROLES_I"; 源代码网推荐 Dictionary<string, object> parameters = new Dictionary<string, object>(); 源代码网推荐 parameters.Add("user_name", userName); 源代码网推荐 parameters.Add("role_name", roleName); 源代码网推荐 try 源代码网推荐 { 源代码网推荐 ExecuteCommand(procedureName, parameters); 源代码网推荐 return true; 源代码网推荐 } 源代码网推荐 catch (Exception ex) 源代码网推荐 { 源代码网推荐 if (ex.Message==ErrorUserNotExists) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The user "{0}" you specify is not existent!", userName); 源代码网推荐 return false; 源代码网推荐 } 源代码网推荐 if (ex.Message==ErrorRoleNotExists) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The role "{0}" you specify is not existent!",roleName); 源代码网推荐 return false; 源代码网推荐 } 源代码网推荐 if (ex.Message == ErrorUserInRole) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The user "{0}" is in the role "{1}"!",userName,roleName); 源代码网推荐 return false; 源代码网推荐 } 源代码网推荐 Console.WriteLine("A unhandled exception is thrown for some unknown reason!"); 源代码网推荐 return false; 源代码网推荐 } 源代码网推荐 } 源代码网推荐 public static void Clear() 源代码网推荐 { 源代码网推荐 ExecuteCommand("P_CLEAR_DATA", new Dictionary<string, object>()); 源代码网推荐 } 源代码网推荐 源代码网推荐 6. Programs 源代码网推荐 源代码网推荐 源代码网推荐 class Program 源代码网推荐 { 源代码网推荐 static void Main(string[] args) 源代码网推荐 { 源代码网推荐 Utility.Clear(); 源代码网推荐 if (Utility.CreateUser("Artech")) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The user "{0}" has been sucessully created!", "Artech"); 源代码网推荐 } 源代码网推荐 if (Utility.CreateUser("Artech")) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The user "{0}" has been sucessully created!", "Artech"); 源代码网推荐 } 源代码网推荐 if (Utility.CreateRole("Administrator")) 源代码网推荐 { 源代码网推荐 Console.WriteLine(" The role "{0}" has been sucessully created!", "Administrator"); 源代码网推荐 } 源代码网推荐 if (Utility.CreateRole("Administrator")) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The role "{0}" has been sucessully created!", "Administrator"); 源代码网推荐 } 源代码网推荐 if (Utility.AddUserInRole("Artech", "Administrator")) 源代码网推荐 { 源代码网推荐 Console.WriteLine(" The user "{0}" has been successfully added in the role "{1}"", "Artech", "Administrator"); 源代码网推荐 } 源代码网推荐 源代码网推荐 if (Utility.AddUserInRole("Dave Crane", "Administrator")) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The user "{0}" has been successfully added in the role "{1}"", "Dave Crane", "Administrator"); 源代码网推荐 } 源代码网推荐 源代码网推荐 if (Utility.AddUserInRole("Artech", "Super Administrator")) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The user "{0}" has been successfully added in the role "{1}"", "Artech", "Super Administrator"); 源代码网推荐 } 源代码网推荐 源代码网推荐 if (Utility.AddUserInRole("Artech", "Administrator")) 源代码网推荐 { 源代码网推荐 Console.WriteLine("The user "{0}" has been successfully added in the role "{1}"", "Artech", "Administrator"); 源代码网推荐 } 源代码网推荐 } 源代码网推荐 源代码网推荐 7. 最终执行结果 源代码网推荐 源代码网推荐
源代码网推荐 源代码网推荐 做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。 源代码网推荐 源代码网供稿. |
