10

I have set up a 1-to-1 relationship using EF code first following the method prescribed here:

Unidirectional One-To-One relationship in Entity Framework

My mapping looks like this ...

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Asset>()
        .HasRequired(i => i.NewsItem)
        .WithOptional(e => e.Asset)
        .Map(m => m.MapKey("NewsItemId"));
}

But when I get this exception ...

A relationship from the 'Asset_NewsItem' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'Asset_NewsItem_Source' must also in the 'Deleted' state.

Whenever this code runs:

var entry = _db.NewsItems.Find(id);

entry.Asset = new Asset();

_db.DbContext.SaveChanges();

I can get things to work if I explicitly mark the previous Asset associated to the NewsItem for deletion, BUT it just seems kinda wonky. It seems like, based on the mapping, the above code should simply work ... replacing the old Asset with the new one.

Am I doing something wrong? Is there something I need to specify in the mapping that will get things working right? Or, is it simply the EF way to have to delete and then add associated objects like this?

Community
  • 1
  • 1
wgpubs
  • 8,131
  • 15
  • 62
  • 109

1 Answers1

8

It is how EF works. You have loaded an entry with related asset and now you want to assign a new asset. This operation will make your old asset unrelated to any entry but it is not allowed by your mapping (you specified that Asset must have related Entry). So you must delete the old asset or assign it to another entry prior to assigning the new asset to satisfy your mapping constraints.

avs099
  • 10,937
  • 6
  • 60
  • 110
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • 3
    Doesn't seem very ORM'ish but I understand what you are saying. Is there a better way to map the relationship that would allow simply setting the new Asset? Or alas, is the mapping right and I just need to deal with it: :) Thanks. – wgpubs Jul 17 '12 at 18:22
  • 1
    I just ran into the same thing. Very frustrating. I believe NHibernate handles this like it should be handled. – Mike Cole Sep 24 '13 at 15:25
  • @MikeCole: and how it should be handled? – Ladislav Mrnka Sep 25 '13 at 15:31
  • 3
    `.Clear()` should clear. `Collection.Remove(item)` should remove the item. I shouldn't have to explicitly tell the ORM to delete it from the database - I should tell my model to remove the item from the collection. IMHO – Mike Cole Sep 25 '13 at 15:45
  • 1
    @MikeCole: First of all there is no collection when working with one-to-one relationship. In my opinion there is no right way to handle this scenario automatically. You can always find a situation where you will need opposite behaviour then the one used by the framework. – Ladislav Mrnka Oct 02 '13 at 11:42
  • 1
    @LadislavMrnka Please help me why I am getting the same error in a situation where no new Asset is being assigned: http://stackoverflow.com/questions/23667190/identity-usermanager-addtorole-throws-exception – Serj Sagan May 21 '14 at 03:19
  • I have similar problem, but in different situation. At the beginning I create new Asset entity ant insert it into database Asset asset= new Asset(); _db.Assets.Add(asset) _db.DbContext.SaveChanges(); everything works as expected. When I delete Asset { var asset = Asset asset= new Asset(); _db.Assets.Find (assetId); _db.Assets.remove(asset); _db.DbContext.SaveChanges();} it works as expected. Table doesn't contain asset. But when I try to insert another asset as is described at in comment, I receive same error which is written in the question. – Rudolf Dvoracek Jun 30 '15 at 16:41
  • @LadislavMrnka I solved my problem described in previous comment with small workaround. I don't use DBContext directly, but it is wrapped as a field inside unit of work pattern. When I use Refresh command for NewsItem entity after Asset deletion, it no longer hold reference to deleted asset. It is sad, because I thought that ObjectContext remember changes in graph. – Rudolf Dvoracek Jul 01 '15 at 13:24
  • @LadislavMrnka, I think MikeCole might have arrived at this answer for the same reason I did which is that this same error occurs when deleting child objects. He might have drawn the same conclusion I did from the answer which is that if the underlying reason is that an entity with a foreign key has to be deleted explicitly then this would hold true for child collections. – Derek Greer Aug 05 '15 at 21:33
  • I returned back to this answer doing some research for an article and found a related post that I thought would be helpful to cross-reference (https://stackoverflow.com/questions/10835439/can-ef-automatically-delete-data-that-is-orphaned-where-the-parent-is-not-delet). The gist, to Mike Cole's statement about how he shouldn't have to tell the ORM explicitly to delete a child object, EF can be configured to handle this, albeit it isn't as straight-forward and intention-revealing as NH's Cascade Delete Orphan. – Derek Greer Feb 18 '18 at 00:10