7

I have a one-to-many uni-directional relationship between Contact and Phone defined like this:

class Contact {
    int ContactId {get; set}
    ICollection<Phone> Phones {get; set}
}
class Phone {
    int PhoneId {get; set;}
    string PhoneNumber {get; set;}
}

Now in the domain layer, i try to do the following:

someContact.Phones.Remove(somePhone);

and when i try to call context.SaveChanges() i get an exception because the relationship is defined as Required (eg. a phone cannot exist without a contact).
How can i solve this without using a foreign key or a navigation property in Phone and without the need to call DbSet<Phone>.Remove(Phone) before calling SaveChanges() ?

Ibrahim Najjar
  • 19,178
  • 4
  • 69
  • 95
  • 1
    can't you just add a `RemovePhone()`-Method to Contact? And what do you want to happen if Mr and Mrs Smith both are in your Database with the same phone and only Mr Smith deletes his account? – efkah Dec 19 '12 at 15:35
  • Do you want the phone to be deleted from the database or just unlinked from the contact? How is EF supposed to know that the phone should be deleted if you don't define a relationship between it and contacts? – lintmouse Feb 08 '13 at 16:23

2 Answers2

1

You basically answered your own question, as the two things you describe are separate:

  1. Unlinking the object
  2. Deleting the object

There may be a clever way for EF to do this, but others have asked the same question and been presented with the answer you alluded to:

e.g. EF 4.1: Removing child object from collection does not delete it - why?

Community
  • 1
  • 1
Matthew
  • 9,851
  • 4
  • 46
  • 77
0

There is a way to do both stapes that Matthew described in the single step. It requires a little change in your model - you have to add foreign key to the Phone entity and create a composite key that contains both PhoneId and ContactId.

This makes the instance of the Phone class tied to the instance of Contact class. With these settings, when you remove a phone from the contact someContact.Phones.Remove(somePhone);, EF removes phone from DB, because it knows that the phone can't exists without connection to that particular contact.

Models:

public class Contact {
    public int ContactId { get; set; }
    public virtual ICollection<Phone> Phones { get; set; }
}

public class Phone {
    public int PhoneId { get; set; }
    public int ContactId { get; set; }
    public string PhoneNumber { get; set; }
}

Configuration:

modelBuilder.Entity<Contact>()
    .HasMany(o => o.Phones)
    .WithRequired()
    .HasForeignKey(f => f.ContactId)
    .WillCascadeOnDelete(true);

modelBuilder.Entity<Phone>()
    .HasKey(o => new { o.PhoneId, o.ContactId });
Lukas Kabrt
  • 5,441
  • 4
  • 43
  • 58
  • you solution is clever, but it violates one of the constraints that i have mentioned in my question so it is hack, and i can find other hacks to do the same think. i wanted to know if it could be done without providing foreign or bi-directional navigation properties and i think (at least in the current version of EF) it can't be done. – Ibrahim Najjar Dec 21 '12 at 23:43