在我們開發WCF項目的時候,常常會碰到一些莫名其妙的錯誤,有時候如果根據它的錯誤提示信息,一般很難定位到具體的問題所在,而由於WCF服務的特殊性,調試起來也不是那麼方便,因此往往會花費不少時間來進行跟蹤處理。本文介紹我在我在我的框架裡面使用WCF服務的時候,出現的一個常見錯誤的處理方法,它的提示信息是:基礎連接已經關閉: 連接被意外關閉。這種情況我碰到的有兩種,一種是返回DataTable的時候出現的,一種是返回實體類類中帶有枚舉類型的情況,下面分別對它們的處理進行介紹。
一般情況下,我們在設計WCF接口返回值的時候,都使用實體類或者實體類列表這種方式,但是有時候也可能需要返回一個DataTable的數據類型,如果按照下面的方式構造函數內容並返回,就可能出現錯誤。
定義接口
/// <summary> /// 根據查詢條件,返回記錄到DataTable集合中 /// </summary> /// <param name="condition">查詢條件</param> /// <param name="pagerInfo">分頁條件</param> /// <returns></returns> [OperationContract] DataTable FindToDataTableWithPager(string condition, ref PagerInfo pagerInfo);
實現函數,為了方便演示,填寫了簡單的測試代碼。
/// <summary> /// 根據條件查詢數據庫,並返回對象集合(用於分頁數據顯示) /// </summary> /// <param name="condition">查詢的條件</param> /// <param name="info">分頁實體</param> /// <returns>指定對象的集合</returns> public DataTable FindToDataTableWithPager(string condition, ref PagerInfo pagerInfo) { //測試代碼 DataTable dt = new DataTable(); dt.Columns.Add("Test"); for (int i = 0; i < 10; i++) { dt.Rows.Add(new object[] { "Test" + i }); } return dt; }
測試的時候,會發現出現錯誤
如果你按照它的提示,你可能搔破頭皮也不知道具體是哪裡的問題,這個地方其實很有意思,就是因為序列號DataTable的時候,沒有TableName導致的,如果把函數體的實現裡面,為返回的DataTable對象的TableName屬性賦值一個值就可以了。
/// <summary> /// 根據條件查詢數據庫,並返回對象集合(用於分頁數據顯示) /// </summary> /// <param name="condition">查詢的條件</param> /// <param name="info">分頁實體</param> /// <returns>指定對象的集合</returns> public DataTable FindToDataTableWithPager(string condition, ref PagerInfo pagerInfo) { //測試代碼 DataTable dt = new DataTable(); dt.Columns.Add("Test"); for (int i = 0; i < 10; i++) { dt.Rows.Add(new object[] { "Test" + i }); } dt.TableName = "test"; return dt; }
測試之後,就發現能夠順利執行了。
實體類定義,定義了一個枚舉的對象ApplyStatus
/// <summary> /// 流程申請單 /// </summary> [DataContract] public class ApplyInfo : BaseEntity { ........ /// <summary> /// 當前狀態(0:處理中,1:已完成,2:已退回,3:已撤消)(其它值為非法值) /// </summary> [DataMember] public virtual ApplyStatus Status { get { return this.m_Status; } set { this.m_Status = value; } } }
枚舉的定義一般情況如果設置如下代碼:
/// <summary> /// 表單當前處理狀態。 /// 當前狀態(0:處理中,1:已完成,2:已退回,3:已撤消)(其它值為非法值) /// </summary> [DataContract] public enum ApplyStatus { /// <summary> /// 處理中 = 0 /// </summary> 處理中 = 0, /// <summary> /// 已完成 = 1 /// </summary> 已完成 = 1, /// <summary> /// 已退回 = 2 /// </summary> 已退回 = 2, /// <summary> /// 已撤消 =3 /// </summary> 已撤消 = 3 }
然後定義WCF服務接口和實現代碼。
WCF接口定義
/// <summary> /// 根據條件查詢數據庫,並返回對象集合(用於分頁數據顯示) /// </summary> /// <param name="condition">查詢的條件</param> /// <param name="info">分頁實體</param> /// <returns>指定對象的集合</returns> [OperationContract] List<T> FindWithPager(string condition, ref PagerInfo info);
WCF服務接口實現
/// <summary> /// 根據條件查詢數據庫,並返回對象集合(用於分頁數據顯示) /// </summary> /// <param name="condition">查詢的條件</param> /// <param name="info">分頁實體</param> /// <returns>指定對象的集合</returns> public List<ApplyInfo> FindWithPager(string condition, ref PagerInfo info) { return bll.FindWithPager(condition, info); }
那麼通過WCF服務獲取這個對象的信息時候,就會出現錯誤:基礎連接已經關閉: 連接被意外關閉
出現錯誤的原因,是因為枚舉類型序列化出現了錯誤,需要在枚舉的值裡面增加[EnumMember]的聲明,如下所示。
[DataContract] public enum ApplyStatus { /// <summary> /// 處理中 = 0 /// </summary> [EnumMember] 處理中 = 0, /// <summary> /// 已完成 = 1 /// </summary> [EnumMember] 已完成 = 1, /// <summary> /// 已退回 = 2 /// </summary> [EnumMember] 已退回 = 2, /// <summary> /// 已撤消 =3 /// </summary> [EnumMember] 已撤消 = 3 }
再次編譯運行並測試,最後的結果就是能夠正常解析了。
以上就是我們在開發WCF的時候,經常碰到的一些錯誤的解決方式,希望大家在開發WCF並進行調用的時候,碰到類似的問題,能夠很好解決問題,節省寶貴的時間。