views:

223

answers:

3

Hi everyone, I'm using Entity framework in web application. ObjectContext is created per request (using HttpContext), hereby code:

string ocKey = "ocm_" + HttpContext.Current.GetHashCode().ToString();
if (!HttpContext.Current.Items.Contains(ocKey))
{
    HttpContext.Current.Items.Add(ocKey, new ElevationEntityModel(EFConnectionString));
}
_eem = HttpContext.Current.Items[ocKey] as ElevationEntityModel;

Not every time, but sometimes I have this exception:

System.Data.MappingException was unhandled by user code Message=The type 'XXX' has been mapped more than once. Source=System.Data.Entity

I'm absolutely confused and I don't have any idea what can caused this problem.

Can anybody help me?

Thanks.

A: 

This is caused when you have multi-threading going on and you are accessing the same ObjectContext without synchronising the threads first...

Calanus
A: 

Thanks and please can you tell me how to synchronize threads?

Michal
A: 

It looks like a synchronisation problem. A simple solution would be to have a shared lock object (within your class):

private static _lock = new object();

Then your code becomes:

string ocKey = "ocm_" + HttpContext.Current.GetHashCode().ToString(); 

lock (_lock) {
    if (!HttpContext.Current.Items.Contains(ocKey)) 
    { 
          HttpContext.Current.Items.Add(ocKey, new ElevationEntityModel(EFConnectionString)); 
    } 
    _eem = HttpContext.Current.Items[ocKey] as ElevationEntityModel; 

}

The lock block basically means that once a thread enters the "lock" block, no other threads can access that block until the first thread finishes. This will stop the contention between the "Contains" method and the "Add" method.

Note: If anywhere else in you application is accessing the Items collection in HttpContext.Current, you will need to synchronise there as well. It is wise to create a custom collection, add this to the Items collection, and synchronise the access to this.

David_001
Thanks you! Now it is fine.
Michal