Well, I have the following model structure: I have one class – DatabaseEntity
which is basically
public class DatabaseEntity
{
public int Id { get; set; }
}
so each entity like product, category etc will inherit DatabaseEntity
and have Id
property. Also I have typical EntityFramework
repository class with InsertOrUpdate
method:
private readonly DbContext _database;
public void InsertOrUpdate<TObject>(TObject entity) where TObject : DatabaseEntity
{
if(entity.Id == default(int))
{
// New entity
DbSet<TObject>().Add(entity);
}
else
{
// Existing entity
_database.Entry(entity).State = EntityState.Modified;
}
_database.SaveChanges();
}
Then I download from eBay via eBay api list of categoies I have to add to database. Basically category is:
public class EbayCategory : DatabaseEntity
{
// It has Id since it inherits DatabaseEntity
public string Name { get; set; }
// ... some other properties
}
But, the problem is, when I download those categories I download and their Id properties, which, of course, already have values. And when I try to save them to database like:
public void UpdateCategories(IEnumerable<EbayCategory> newCategories)
{
foreach (var newCategory in newCategories)
{
_repository.InsertOrUpdate(newCategory);
}
}
I face some issues… First of all, entity.Id != default(int)
because it has value, so repository tries to update this entity, instead of adding, but it is not in the database or context so it throws the following exception:
System.Data.Entity.Infrastructure.DbUpdateConcurencyException
"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."
… because it thinks that someone else deleted entity which I am trying to update. How can I save this InsertOrUpdate logic, since a lot of projects are based on it, and be able to add items (EbayCategories
) with primary key (Id
) to database and then update/delete them like other entities without discarding EbayCategory.Id
value?
2
Answers
To allow you to manually generate Ids you need a class that has a manually generated ID – so it cannot inherit from
DatabaseEntity
Now you will need a different
InsertOrUpdate
to handle entities that have manually generated keys:Colin’s answer above quite correctly shows how to achieve this setting using data annotations.
But in the presented problem the entity is a subclass so you can’t add the annotation without changing the entity class.
There is an alternative configuration method: Fluent Configuration. Here’s my example using an EntityTypeConfiguration class:
You can also add configuration directly to the modelBuilder as per this post: https://stackoverflow.com/a/4999894/486028