Quick Summary I have two scenarios --
- A
Person
has aPersonalAddress
with anAddress
that belongs only to them. - A
Person
has aPersonalAddress
with anAddress
that is a sharedCorporateAddress
.
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