谈谈基于SQL Server 的Exception Handlingp[下篇]
在上面一節(jié)中,我給出了一個完整的例子說明了:如何在將message定義在sys.messages中保證message的一致性和可維護(hù)性;如何在Stored procedure中使用RAISERROR將一個可預(yù)知的Error拋出;如何在Stored procedure中使用TRY/CATCH進(jìn)行異常的捕捉;在Application如果處理從SQL Server拋出的Exception。實際上,SQL Server database Engine拋出、被我們的.NET最終捕獲的SqlException,我們通過SqlException的屬性可以得到Error的相關(guān)信息。下面是SqlException的屬性列表:
?
- public SqlErrorCollection Errors { get; }
- public int LineNumber { get; }
- public int Number { get; }
- public string Procedure { get; }
- public string Server { get; }
- public override string Source { get; }
- public byte State { get; }
有了前面的內(nèi)容作鋪墊,相信大家都知道每個屬性分別表示的什么了吧。為了使大家對
?
在stored procedure中,遇到重名通過RAISERROR拋出異常[在整篇文章中,使用到Error和Exception,大家可以看成是等效的]:
????·???????? Error Number:50001
????·???????? Severity:16
????·???????? State:1
????·???????? Message:This user is already existent
我們來修正一下CreateUser方法:
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?(SqlException?ex)
????????????{
????????????????Console.WriteLine("ex.Class\t:?{0}",?ex.Class);
????????????????Console.WriteLine("ex.ErrorCode\t:?{0}",?ex.ErrorCode);
????????????????Console.WriteLine("ex.LineNumber\t:?{0}",?ex.LineNumber);
????????????????Console.WriteLine("ex.Message\t:?{0}",?ex.Message);
????????????????Console.WriteLine("ex.Number\t:?{0}",?ex.Number);
????????????????Console.WriteLine("ex.Procedure\t:?{0}",?ex.Procedure);
????????????????Console.WriteLine("ex.Server\t:?{0}",?ex.Server);
????????????????Console.WriteLine("ex.Source\t:?{0}",?ex.Source);
????????????????Console.WriteLine("ex.State\t:?{0}",?ex.State);
?????????return?false;
????????????}
????????}
在Main()中調(diào)用這個CreateUser():
在這里我想特別說明一下SqlException.Number這個屬性,它代表Database中的Error number[或者是@@ERROR、imessage_id],不過當(dāng)我們使用RAISERROR語句,如果我們指定的一個表示error message的字符串,ADO.NET捕獲的SqlException.Number這個屬性默認(rèn)為50000。比如我們將Error number換成error message:
SET?@error_serverity????=ERROR_SEVERITY()
SET?@error_state????=?ERROR_STATE()
RAISERROR(@error_message,?@error_serverity,@error_state)
將會得到這樣的結(jié)果:
還有一點需要特別提醒得是,我們可以在調(diào)用RAISERROR加了一個WITH SETERROR重句,強(qiáng)制將當(dāng)前@@ERROR的值返回到客戶端:
七、??? InfoMessage
上面的所以內(nèi)容都圍繞一個Exception handling的主題,在文章最后一部分我們想想一個和非Exception handling但是又和上面的內(nèi)容很相關(guān)的主題:在Database通過Print語句輸出的Message如何向Application傳遞。
在上面的例子中,有一個P_CLEAR_DATA的stored procedure,用于數(shù)據(jù)的清理。在操作結(jié)束后,有一個Print語句(PRINT ('All data have been deleted!'))
CREATE?Procedure?P_CLEAR_DATA
AS
????DELETE?FROM?dbo.T_USERS_IN_ROLES
????DELETE?FROM?dbo.T_USERS
????DELETE?FROM?dbo.T_ROLES
????
????PRINT?('All?data?have?been?deleted!')
????
GO
我們的現(xiàn)在的目標(biāo)是在Application中,如何得到這段Message。要做到這點很簡單,只需要用到SqlConnection的InfoMessage事件,當(dāng)通過DbCommand執(zhí)行上面一段Sql的時候,Print語句的執(zhí)行將出發(fā)該事件。我們現(xiàn)在要做的就是注冊這個事件,比如下面我們在ExecuteCommand()種添加了下面一段代碼:
SqlConnection?sqlConnection?=?connection?as?SqlConnection;
?if?(sqlConnection?!=?null)
????{
??????????sqlConnection.InfoMessage?+=?delegate(object?sender,?SqlInfoMessageEventArgs?e)
??????????{
????????????????????????Console.WriteLine(e.Message);
???????????};
?????}
?當(dāng)我們調(diào)用Utility.Clear()的時候,就會輸出"All data have been deleted!"
[原創(chuàng)]談?wù)劵赟QL Server的Exception Handling - PART I
[原創(chuàng)]談?wù)劵赟QL Server 的Exception Handling - PART II
[原創(chuàng)]談?wù)劵赟QL Server 的Exception Handling - PART III?
轉(zhuǎn)載于:https://www.cnblogs.com/artech/archive/2007/12/17/1002857.html
總結(jié)
以上是生活随笔為你收集整理的谈谈基于SQL Server 的Exception Handlingp[下篇]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: premature end of fil
- 下一篇: 从数据库读写RadioButtonLis