0

Quick Summary I have two scenarios --

  1. A Person has a PersonalAddress with an Address that belongs only to them.
  2. A Person has a PersonalAddress with an Address that is a shared CorporateAddress.

When a user tries to delete a person's address in case 1, both the PersonalAddress as well as the related Address need to be deleted. (I currently have this working.)

When a user tires to delete a person's address in case 2, the PersonalAddress record needs to be deleted but the Address record needs to remain since it is tied to a CorporateAddress. This is where I'm having trouble. I cannot seem to delete the PersonalAddress if I don't also delete the Address.

Details of my setup

My business requirements are that I need a common list of addresses. Some of these addresses are corporate addresses and some are personal addresses. However, there are many individuals who use corporate addresses as personal addresses. In this case, we'd rather reference the existing address rather than create a new address so that if the corporate address changes, anyone sharing that address is updated as well.

I have the following POCO objects (which I'll abbreviate to make things simpler)

public class Person {
   ...
   public ICollection<PersonalAddress> Addresses {get; private set;}
}

public class PersonalAddress {
   public int Id {get; set;}
   public Address Address {get; set;}  //not defining foreign key property here
   public PersonalAddressType AddressType {get; set;}
   public DateTime? StartDate {get; set;}
   ...
}

public class Address {
   public int Id {get; set;}
   public string Street1 {get; set;}
   public string Street2 {get; set;}
   ...
}

public class CorporateAddress {
  public int Id {get; set;}
  public int AddressId {get; set;}  //foreign key to address table
  public Address Address {get; set;}
  public string Description {get; set;}
  ...
}

These have the following EF mappings:

modelBuilder.ToTable("persons");
modelBuilder.Entity<Person>()
  .HasMany(p => p.Addresses)  //PersonalAddress
  .WithRequired().Map(m => { m.MapKey("personId"); } );

modelBuilder.Entity<Address>().ToTable("addresses");
modelBuilder.Entity<Address>().HasKey(a => a.Id);

modelBuilder.Entity<PersonalAddress>().ToTable("PersonalAddresses");
modelBuilder.Entity<PersonalAddress>()
   .HasRequired(p => p.Address)
   .WithMany()
   .Map(m => {m.MapKey("addressid");}); //map FK because not defined on object

modelBuilder.Entity<CorporateAddress>().ToTable("corporateAddresses");
modelBuilder.Entity<CorporateAddress>()
   .HasRequired(c => c.Address)
   .WithMany()
   .HasForeignKey(c => c.AddressId);

With all of this, I can successfully add and update addresses both on the Corporate side as well as on the personal side. I can also add a personal address that references an existing corporate address.

If I try to delete a personal address that is NOT tied to a corporate address, I can do so with the following:

var _person = _context.Persons
    .Include(p => p.Addresses.Select(a => a.Address))
    .SingleOrDefault(p => p.Id == personId);

var _address = _person.Addresses.SingleOrDefault(a => a.Address.Id == addressId);

_person.Addresses.Remove(_address); \\gets rid of the PersonalAddress
_context.Set<Address>().Remove(_address.Address); \\gets rid of the Address
_context.SaveChanges();

However, in cases where the address is shared, I don't want to delete the Address, I just want to delete the PersonalAddress. Trying the above does not work (granted, I don't execute the second line -- removing the address).

I also tried the following:

_address.Address = null; \\Destroy the link to the Address
_person.Addresses.Remove(_address); \\gets rid of the PersonalAddress
_context.SaveChanges();

In this case, neither the personal address nor the address get deleted.

How does one accomplish something like this in EF -- or am I just pushing the limits of what EF can do.

I'm using EF 5.0

RHarris
  • 10,641
  • 13
  • 59
  • 103
  • Do you have CascadeDelete on? – Vlad274 Oct 05 '15 at 17:52
  • I set it to `false` because, as my example shows, I don't want the `Address` deleted in this case, I actually want to leave the `Address` but delete the `PersonalAddress`. – RHarris Oct 05 '15 at 18:20
  • When you say "neither the personal address nor the address get deleted", is the link from Person to Address removed? IE is personId set to null? – Vlad274 Oct 05 '15 at 19:34
  • Are you asking if I programmatically set PersonId to null or if the PersonId is set to null after calling `_context.SaveChanges()`? – RHarris Oct 06 '15 at 12:50
  • After calling SaveChanges(). I'd look in the DB to see. – Vlad274 Oct 06 '15 at 12:52
  • No, PersonId is not being nulled out in DB. (Its a non-nullable field because `PersonalAddress` must always be tied to a `Person`. No error is thrown during `SaveChanges()` but its almost as if `SaveChanges()` ignores the delete of `PersonalAddress` if there is no delete of `Address`. – RHarris Oct 06 '15 at 12:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/91491/discussion-between-vlad274-and-rharris). – Vlad274 Oct 06 '15 at 12:59

1 Answers1

0

Try setting the address State to EntityState.Deleted.

smurtagh
  • 529
  • 6
  • 17