在我們開發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並進行調用的時候,碰到類似的問題,能夠很好解決問題,節省寶貴的時間。