This project is read-only.
1
Vote

Loading new items to collection which already have another new items crash

description

When I try to load items to collection which already have another new items (EntityState == EntityState.New), I got "An item with the same key has already been added." exception and after investigation I found problem in lines of Import method:
foreach (T currentEntity in collection)
{
identityCache.Add(currentEntity.GetIdentity(), currentEntity);
}
It try to add two items with ID = 0 from collection (I used int for ID and I have two new items in collection).
 
My solution propose is to add condition to add only not new entities:
foreach (T currentEntity in collection)
{
if (currentEntity.EntityState != EntityState.New)
{
    identityCache.Add(currentEntity.GetIdentity(), currentEntity);
}
}

comments

JoeBrockhaus wrote May 29, 2012 at 3:04 PM

this will likely stay as is and is 'by design' because as everything is key-based, you cannot have multiple entities with the same key in the collection. If it were relaxed for Contrib, you would invariably run into the issue with the CLR code.

Two different entity instances of the same type cannot share the same key value. For instance, if EntityB references Entity1, but Entity2 has the same key value (0), which one should the reference actually point to?

You'll have to assign a temporarily unique key value to entities in EntityState.New (use a 'factory' method on the client that auto-increments an item-created count, using a lock{}), use an Invoke method in your DomainService to retrieve a new key value from the database (rather than generating a temporary key), or use a LoadOperation that returns a single new entity with the key from the database rather than using new Entity() in the client.

Each of these has their various pros/cons, but hopefully this helps you on your way. (If you use a temporary key value, then before saving related entities with FKs that were previously temporary, you will have to manually update these prior to saving them. This means you have to save your entity hierarchy top-down when inserting, which is a bit tedious to deal with because you'll notice the InsertEntity methods in your DomainService will get called bottom-up..)

JoeBrockhaus wrote May 29, 2012 at 3:09 PM

(You could also change your ID types to Guid, and generated a NewGuid when entities are created .. but sometimes Guids can be bad for database and wire performance because of their random order and length.)