none
Exception: Cannot access a disposed object (after making new DataContext) RRS feed

  • Question

  • Hello,

    I have an application that has a DataGrid for most of a user interface. I use one DataContext (DC) for the DataGrid and another DC for other UI elements. Other applications may update the database outside the scope of my application and its DCs, so I need a way to refresh the DC to see anything new. It has been widely suggested that the best approach for retrieving new data from the backend is to get a new DataContext and re-run queries. So prior to instantiating a new DC to set the DataGrids ItemSource property, I thought I'd first Dispose of the existing DC. After trying this, my application is now getting "Cannot access a disposed object" exceptions at certain points.

    I suspect that some Entities EntitiySet memebers are hanging on to their original DC because of deffered loading. If this is the case, do I need to be doing something more than just calling Dispose on my DC? What is the proper way to Dispose of a DC and build a new one for use as UI DataContext?

    Thanks,


    Bill McCormick -- MSDN Subscriber
    Wednesday, May 5, 2010 7:38 PM

Answers

  • The problem was that I was getting a selected row from my DataGrid in the wrong way. Instead of looking at the AddedItems and RemovedItems arrays, I trying to get the selected row from the sender object inside inside the event. Well, the Entity that I was getting in that way appears to have been the Entity from the previous DataContext. Once I started using the Entity from the AddedItms arrays, I had much less of a problem.

    The DataLoadOptions did however help with another issue.

    Thanks,


    Bill McCormick -- MSDN Subscriber
    Saturday, May 8, 2010 3:15 PM

All replies

  • The proper way would be to have a using statement at your DataContext.

    The reason that you get the exception is that you are trying to get some data after your DataContext is disposed, this typically happens when returning IQueryable from the method using your DataContext. If you want to use your data which your object graph can consist of, you have to load the related table data using DataLoadOptions

     

    DataLoadOptions options = new DataLoadOptions();
    db.LoadOptions = options;
    options.LoadWith((Customer c) => c.Orders);
    

     

    Please take a look here for more details: http://msdn.microsoft.com/en-us/library/system.data.linq.dataloadoptions.loadwith.aspx

     

     

    It has been widely suggested that the best approach for retrieving new data from the backend is to get a new DataContext and re-run queries

     

    Yes, absolutely that is correct, never push an open DataContext around.

    Wednesday, May 5, 2010 8:55 PM
  • I don't see how it would be possible to wrap in a using block the DataContext that is used to produce a query that sets the ItemsSource for a data grid.

    For example, when my page loads I do this:

    JobListGrid.ItemsSource = appData.OrderDataList;
        public IEnumerable<JobOrdTable> OrderDataList
        {
          get
          {
            string PlantId = Plant.Id;
    
            try {
              return from c in this._dbJobList.JobOrdTables
                  where c.OrdMixID == "SCALE"
                  && c.OrdPltId == PlantId
                  && c.JobOrdStatus != (short)JOBSTATUS.Setup
                  && c.JobOrdStatus != (short)JOBSTATUS.Complete
                  orderby c.JobStartDate descending
                  select c;
            } catch (Exception ex) {
              CEAL.CEALException("Exception building order list", ex);
              return null;
            } 
          }
        }
    
    

    So if the _dbJobList DataContext is disposed after the query runs, there won't be any data in my JobListGrid DataGrid. Maybe I'm missing something very basic?

    With regard to DataLoadOptions, I assume that you mean to suggest that I set DeferredLoadingEnabled = false for the DataContext? I'd rather not as for very large data sets this would severly impact performance.

    Thanks,

     


    Bill McCormick -- MSDN Subscriber
    Wednesday, May 5, 2010 9:21 PM
  • In such a case like that I would return a List instead...

    public IList<JobOrdTable> OrderDataList
    ..
    .. select c.ToList() ..

    When I said DataLoadOptions, I didn't mean Load All :), but simply choosing which entities to load into your main object. As I see your statement now, I can see that you are not working with such, it would have been another story if you wanted to retrieve a child entity from JobOrdTable, for instance if it was related to another called JobOrderDetails.

    Then I would do like:

    DataLoadOptions options = new
    
    DataLoadOptions();
    db.LoadOptions = options;
    options.LoadWith((JobOrdTables c) => c.JobOrdDetails);

     

    Please write again if you need more help with this issue...

    Kind regards

    Janus C. H. Knudsen

    Thursday, May 6, 2010 7:28 AM
  • The problem was that I was getting a selected row from my DataGrid in the wrong way. Instead of looking at the AddedItems and RemovedItems arrays, I trying to get the selected row from the sender object inside inside the event. Well, the Entity that I was getting in that way appears to have been the Entity from the previous DataContext. Once I started using the Entity from the AddedItms arrays, I had much less of a problem.

    The DataLoadOptions did however help with another issue.

    Thanks,


    Bill McCormick -- MSDN Subscriber
    Saturday, May 8, 2010 3:15 PM
  • I appreciate you could use my help :)
    Saturday, May 8, 2010 8:15 PM