Tuesday, April 5, 2011

Passing LinqDataSource through Session: 'DataContext accessed after Dispose.'

I´m in need to pass some results from the database around. Instead of pass a whole dataset, or a constructed sql query, I tried to pass a LinqDataSource configured object.

On the source page, I configure the LinqDataSource object properties Where and WhereParameters using the values set by the user on the controls displayed on the page (search box, combo box etc.). I pass the object around to avoid the LinqDataSource reconfiguration on the receiver page.

But, even while it worked fine on my developing system, after deploying it on a dedicated server I got an error saying the following:

Cannot access a disposed object.

Object name: 'DataContext accessed after Dispose.'.

On both pages, the source and the receiver, the LinqDataSource objects are declared as:

<asp:LinqDataSource ID="myLinqDS" runat="server" 
    ContextTypeName="MyProject.MyDBNamedpace.MyDataContext" 
    TableName="TheTable"
    OrderBy="field1, field2"
</asp:LinqDataSource>

To pass the datasource object around I do this:

SetLinqDataSourceWhereAndHisParameters(); //just set Where and WhereParameters
Guid guid = Guid.NewGuid();
Session[guid.ToString()] = myLinqDS;
ScriptManager.RegisterStartupScript(this.Page,
    typeof(Page),
    "Redirect",
    String.Format(@"window.open(""{0}"");",
        this.ResolveClientUrl("~/PageToDisplayTheData.aspx?guid=" +
        System.Web.HttpUtility.UrlEncode(guid.ToString())
    ),
true);

And to retrieve, on PageToDisplayTheData.aspx´s codebehind:

myLinqDS =
   (LinqDataSource)Session[System.Web.HttpUtility.UrlDecode(Request.QueryString[guid])];
aDataList.DataSource = myLinqDS;
aDataList.DataBind();
From stackoverflow
  • What is your goal? If you want to keep the application from having to go back to the database, then you will need to cache the entire dataset anyway. If you are simply trying not have have to recreate the query, why not add the query to your data context as a method and reference it from there everywhere.

    public partial class MyDataContext
    {
        public Table<MyTable> OrderedTable()
        {
             return this.TheTable.OrderBy( t => t.field1 )
                                 .ThenBy( t => t.field2 );
        }
    }
    
    Seiti : The result set is filtered using user provided data: search, combo boxes, radiobuttons etc. In the example above I encapsulated that logic on SetLinqDataSourceWhereAndHisParameters().
    Seiti : And I know that passing the LinqDataSource will hit the database again, because of the linq behavior. I just wanted to avoid passing less info and have to repeat operations (DRY?)
  • Just copied the properties from one object to the another and it worked:

    LinqDataSource received=
    (LinqDataSource)Session[System.Web.HttpUtility.UrlDecode(Request.QueryString[guid])];
    
    myLinqDS.Where = received.Where;
    foreach (Parameter p in received.WhereParameters)
        myLinqDS.WhereParameters.Add(p);
    

    But I still don´t know why it worked on VS2008 internal web server but not on the main server, running IIS.

  • You should not be storing the DataContext in Session (or anywhere) for the following reasons:

    • The DataContext isn't thread safe
    • The DataContext is designed as a Unit-Of-Work tool

    If you query a collection within the DataContext it is internally cached, so when you requery it you don't do a round-trip to the database. But this can lead to data stagnation as the values don't reflect what the actual state of the underlying database.

0 comments:

Post a Comment