[Code]ObjectDataSource with Linq to SQL (DataContext disposed error)

ObjectDataSource with Linq to SQL (DataContext disposed error)

架構上, 我們會有一個Business的Object去handle商業邏輯,

所以為類別增加…


	using System.ComponentModel;

[DataObject(true),Serializable()]
public class ...

並希望能夠reuse DataContext,


	internal DataClassesDataContext context;

    public BizObject() {
        context = new DataClassesDataContext();
        context.Log = new DebugTextWriter();
    }

    public BizObject(DataClassesDataContext context)
	{
        this.context = context;
	}

    public BizObject(Utilities u) {
        context = u.context;
    }

為了怕 DataContext沒有release,

 


	public class BizObject :IDisposable
{
    #region IDisposable 成員

    public void Dispose() {
        try {
            if (context != null)
                context.Dispose();
        } catch (Exception) { }
    }

    #endregion

 

在使用者界面上, 使用GridView 並引用ObjectDataSource來 binding,

在預設狀況, 因為ObjectDataSource 在做Select operation後會將 DataObject Dispose掉,

所以, 就會收到這樣的錯誤

無法存取已處置的物件。
物件名稱: 'DataContext 在 Dispose 之後被存取。'。
描述: 在執行目前 Web 要求的過程中發生未處理的例外情形。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。

例外詳細資訊: System.ObjectDisposedException: 無法存取已處置的物件。
物件名稱: 'DataContext 在 Dispose 之後被存取。'。

故, 我們得接管ObjectDataSource的生命週期

(1) 宣告全域變數, 並於初始階段, 建立物件


	internal BizObject utilities;

    protected void Page_Init(object sender, EventArgs e) {
        utilities = new BizObject();
    }

(1) oncreating, 指定物件實體為全域變數之物件

aspx:


	<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
onobjectcreating="ObjectDataSource1_ObjectCreating" />

cs:


	protected void ObjectDataSource1_ObjectCreating(object sender, ObjectDataSourceEventArgs e) {
        e.ObjectInstance = utilities;
    }

(2) onobjectdisposing, 取消預設程序


	protected void ObjectDataSource1_ObjectDisposing(object sender, ObjectDataSourceDisposingEventArgs e) {
        e.Cancel=true;
    }

 

(3) 最後是釋放, (註: for postback only)


	protected void Page_Unload(object sender, EventArgs e) {
        Release();
    }

    protected void Page_Error(object sender, EventArgs e) {
        Release();
    }

    private void Release() {
        try {
            if (utilities != null)
                utilities.Dispose();
        } catch (Exception) {
        }
    }

 

 

BTW, ObjectDataSource + GridView + LinqToSql 個人覺得並不好用,

因為Update時, LinqToSql 需要將DataContext取回的物件做PropertyChange, 才能SubmitChange(),

但這樣的架構下, 因為GridView的Update event是將資料bind到一個自建的資料物件, 所以無法正常變更, 必須另外加取物件 + PropertyChange 有點麻煩

Deleted 時也是同樣情況, 但 ObjectDataSource_OnDeleting事件並不能對InputParameter進行修改(唯讀),

以上導致原本的BizObject 得為這些狀況另外Coding …

如果有什麼好解決方案, 請各位大大不吝指教, 謝謝