I have code that receives list of operations to execute. This list can contain "add new" object and right after this "update" this entity operation. Code example:
public void RunBulk(IList<BulkItem> bulk)
{
using (var transaction = _dbContext.Database.BeginTransaction())
{
try
{
foreach (var bulkItem in bulk)
{
var entity = bulkItem.Item;
if (entity != null)
{
var entityType = entity.GetType();
switch (bulkItem.Operation)
{
case BulkOperation.Update:
{
_dbContext.Entry(entity).State = EntityState.Modified;
_dbContext.Set(entityType).Attach(entity);
break;
}
case BulkOperation.Write:
_dbContext.Set(entityType).Add(entity);
break;
}
}
}
_dbContext.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
}
}
}
When SaveChanges() is called i get
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: Saving or accepting changes failed because more than one entity of type 'MyType' have the same primary key value. Ensure that explicitly set primary key values are unique. Ensure that database-generated primary keys are configured correctly in the database and in the Entity Framework model. Use the Entity Designer for Database First/Model First configuration. Use the 'HasDatabaseGeneratedOption" fluent API or 'DatabaseGeneratedAttribute' for Code First configuration.
Table in database doesn't have identity or computed fields, so they all should be specified manually.
Is there any way to execute this type of operations "correctly" without getting exception?
UPD: I have working piece of code which uses NHibernate. Is it possible to get same functionality with EF?
UPD2: Probably i need analog for nhibernate Merge() method. I have seen somewhere AddOrUpdate() method in EntityFramework, but for some reason it's not available for me. Entity Framework Code First AddOrUpdate method insert Duplicate values
switch (bulkItem.Operation)
{
case BulkOperation.Remove:
nhibernateSession.Delete(nhibernateSession.Merge(entry));
break;
case BulkOperation.Write:
case BulkOperation.Update:
if (retries > 0 || _useMerge)
nhibernateSession.Merge(entry);
else
{
try
{
nhibernateSession.SaveOrUpdate(entry);
}
catch (HibernateException)
{
nhibernateSession.Merge(entry);
}
}
break;
default:
break;
}