This is a migrated thread and some comments may be shown as answers.

Context getting Disposed

5 Answers 628 Views
Development (API, general questions)
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Phil
Top achievements
Rank 1
Phil asked on 10 Dec 2012, 10:46 PM
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?

5 Answers, 1 is accepted

Sort by
0
Dimitar Tachev
Telerik team
answered on 13 Dec 2012, 05:31 PM
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.
0
Phil
Top achievements
Rank 1
answered on 14 Dec 2012, 11:10 AM
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
0
Damyan Bogoev
Telerik team
answered on 19 Dec 2012, 08:30 AM
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.
0
Phil
Top achievements
Rank 1
answered on 19 Dec 2012, 10:24 PM
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
0
Accepted
Dimitar Tachev
Telerik team
answered on 21 Dec 2012, 04:15 PM
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.
Tags
Development (API, general questions)
Asked by
Phil
Top achievements
Rank 1
Answers by
Dimitar Tachev
Telerik team
Phil
Top achievements
Rank 1
Damyan Bogoev
Telerik team
Share this question
or