Reputation: 639
I have a problem when adding posts to my DB, this "Add" function is called from multiple threads. And usually very quick after eachother, I dont know if this matters, but thats the way it works.
Code:
private object dbLock = new object();
public void Add(string fileName, DateTime collectionTime)
{
try
{
lock (dbLock)
{
var collection = new Collection
{
Filename = fileName,
Datetime = collectionTime,
};
_entities.AddToCollection(collection);
_entities.SaveChanges();
CollectionChanged(collection, null);
}
}
catch (Exception ex)
{
}
finally
{
}
}
My problem is that when SaveChanges is called I get this exception:
The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.
All answers I managed to find has something to do with that you have to add StoreGeneratedPattern="Identity"
, I allready did this, but it doesn't help
<Property Name="ID" Type="integer" Nullable="false" StoreGeneratedPattern="Identity" />
So is there any other way to solve this?
Upvotes: 1
Views: 515
Reputation: 1063964
Ultimately, sharing an object-context between threads is a really really bad idea. An object-context is intended to be used as a unit of work - i.e. short-lived; typical usage:
using(var ctx = new SomeObjectContextType()) // assuming IDisposable
{
// not shown: get some records, if needed
...
// not shown: update, add, remove some records, if needed
ctx.SaveChanges();
} // and now it is gone, never to be used again
It might get a bit more complex than that in some scenarios, for example keeping an object-context for the duration of a page / request, but it should not be shared between callers. The reasons for this are many, but fundamentally all competing updates would need to be locked, and "updates" here includes the simple act of reading any record from a database, or lazily loading a property. It should not be surprising that an object-context gets temperamental when accessed by multiple threads: that scenario is not (usually) supported.
Additionally, there are other issues with having a long-lived object context:
Dispose()
it if appropriate) - and forget about it; if you want to reapply your change, you start from a fresh object-contextBasically, the "fix" here is: don't do that. That isn't the correct usage of an object-context. Do not have an application-wide shared object context.
Upvotes: 3