Context getting Disposed

6 posts, 1 answers
  1. Phil
    Phil avatar
    8 posts
    Member since:
    Dec 2010

    Posted 10 Dec 2012 Link to this post

    I am using an ObjectAccessLINQDataSource, which I wish to initiate using a custom ConnectionString (using non-integrated security, and current user logged in). The documentation mentions 3 techniques for managing the dbContext of the OALDS, 1st 2 of which are:
    1. Using master pages to hold the context
    2. using httpcontext, and the ContextFactory code supplied.

    Simple cases all seem to work fine. Problem occurs when you update the record, using auto-configuration, not coded, and custom initialising the context. It appears that updating records all works fine if you use wizard configuration, that only supports fixed connection strings,
    BUT
    When you initialise the context, using the OALDS OnContextCreating event, work until AFTER you do an update, which by the way succeeds as far as updating the record in the dataset, but when it then reacquires the data from the source, an exception is thrown:
    System.ObjectDisposedException was unhandled by user code
      Message=The context has already been disposed and it's managed persistent objects can no longer be accessed. The context should be disposed at the end of the life cycle of your business logic instance. This can also be done in the Dispose of your ASP page or MVC controller.
    Object name: 'Telerik.OpenAccess.OpenAccessContextBase'.
      Source=Telerik.OpenAccess
      ObjectName=Telerik.OpenAccess.OpenAccessContextBase
      StackTrace:
           at Telerik.OpenAccess.OpenAccessContextBase.CheckNotDisposed()
           at Telerik.OpenAccess.OpenAccessContextBase.GetScope()
           at Telerik.OpenAccess.OpenAccessContext.GetAllCore[T]()
           at Telerik.OpenAccess.OpenAccessContext.GetAll[T]()
           at WebClient.DataEntities.get_Accounts() in C:\Users\pholmes\Documents\Development Projects\Sirrus\WebClient\WebClient\EntityDiagrams.cs:line 82
      InnerException: 

    Important points here. I have NOT disposed the context. I have even put event handler in on the OALDS OnContextDisposing event to see if it is getting fired, and it is not.

    Any input here?

  2. Dimitar Tachev
    Admin
    Dimitar Tachev avatar
    67 posts

    Posted 13 Dec 2012 Link to this post

    Hi Phil, 

    OpenAccessLinqDataSource is disposing its context after each CRUD operation and using the same instance instead of creating a new one is not supported. 

    In order to use your custom ConnectionString you could replace the GetContextPerRequest method in the ContextFactory with the following one:
    public static EntitiesModel GetContextPerRequest()
    {
        string connectionString = "..."; // build you custom connection string here
        EntitiesModel newContext = new EntitiesModel(connectionString);
        return newContext;
    }

    This approach will create a new OpenAccessContext instance with the correct connection string for each request.

    I hope that helps.

    Greetings,
    Dimitar Tachev
    the Telerik team
    Telerik OpenAccess ORM Meets ASP.NET Web API. Read more.
  3. DevCraft banner
  4. Phil
    Phil avatar
    8 posts
    Member since:
    Dec 2010

    Posted 14 Dec 2012 Link to this post

    Thanks Dimitar,

    Yes, I guess that does solve this specific problem, but just by way of a more 'all cases' solution, it appears that this event is only happening after CRUD operations (as you said), but in all other OA cases of context use, the context is maintained, and from your documentation, it is recommended to share this context. For clean-up, on section of the documentation (master page based maintenance of context), it also says you should specifically dispose the context on the parent dispose event. Seems to be a little confusion here.

    In a similar solution to what you suggested & trapped this exception in the ContextFactory call as per below:
    if (context == null ) {
        context = new DataEntities(connectionString);
        httpContext.Items[key] = context;
    } else {
         // check if context has been disposed
        try { context.Accounts.First(); }
        catch (ObjectDisposedException e) {
            context.Dispose();
            context = new DataEntities(connectionString);
            httpContext.Items[key] = context;
        }
    }

    Not trying to make this too hard here, just concious that in the end this app will have a lot of users hitting it, and if I'm constantly creating contexts and not cleaning them up, I would have thought I may have memory problems later, so:
    1) Am I wasting my time here, and the dbcontexts always automatically get disposed anyway?
    2) Is there a better code-way (than above) to check if the post CRUD op disposal has happened, and re-init if so?

    Thanks,
    Phil
  5. Damyan Bogoev
    Admin
    Damyan Bogoev avatar
    581 posts

    Posted 19 Dec 2012 Link to this post

    Hello Phil,

    It is a good practice the OpenAccessLinqDataSource to handle the underlying OpenAccessContext instance internally. The data source control will initialize its context when it is needed and you do not need to try to provide it with a shared context instance. 

    Actually using shared context instance in this scenario can lead to subtle issues. It is possible this context to be already used for another CUD operations and committing the Linq data source current changes will persist the other changes as well. 

    If any other questions arise, do not hesitate to contact us back. 


    All the best,
    Damyan Bogoev
    the Telerik team
    Telerik OpenAccess ORM Meets ASP.NET Web API. Read more.
  6. Phil
    Phil avatar
    8 posts
    Member since:
    Dec 2010

    Posted 19 Dec 2012 Link to this post

    Thanks Damyan,

    All good except for one thing. Letting the DataSource manage the context always results in it calling the default constructor, which uses a fixed connection sting. My purpose here is that in this application, we want to take the FormsIdentity login through into the SQL connectionstring, so that we can track & manage, who is logged in at a SQL Server level.

    The connection pooling logic correctly pools connections only with the same connectionstring, by design resulting in separate connections for each logged in user (as we require here). We need to call the context constructor with a user-specific connection string, which does not appear possible if we leave it to the DataSource to manage.

    Please advise.
    Phil
  7. Answer
    Dimitar Tachev
    Admin
    Dimitar Tachev avatar
    67 posts

    Posted 21 Dec 2012 Link to this post

    Hi Phil,

    Please excuse us for the inconvenience caused. 

    I reviewed the OpenAccessLinqDataSource documentation and found out that there is an issue in the section for managing the OpenAccess context – it will be addressed.

    The data source is disposing its context on each operation and in any way that you try to get the same instance it will already be disposed. 

    After all, the solution that I prepared for you (the one that is creating a new context with custom connection string on each request) will meet all of your needs and you do not have to worry about any memory problems.

    Hope this clarifies things.

    Regards,
    Dimitar Tachev
    the Telerik team
    Q3'12 SP1 of OpenAccess ORM packs Multi-Table Entities mapping support. Check it out.
Back to Top
DevCraft banner