I need to create a relationship where I have a user table that links to an address table. The problem is that I need the address table to also store historic addresses. It is also possible that a user might not have an address at all.
public class user
{
public virtual int ID { get; set; }
...
public virtual int? AddressId { get; set; }
[ForeignKey("AddressId")]
public virtual Address CurrentAddress { get; set; }
public virtual ICollection<Address> HistoricAddresses { get; set; }
}
public class Address
{
public virtual int ID { get; set; }
...
}
I tried various ways to get this to work and got various errors like putting another table between User and Address:
public class HistoricAddress
{
public virtual int ID { get; set; }
public Address HistoricAddress { get; set; }
}
public class user
{
public virtual int ID { get; set; }
public virtual Address CurrentAddress { get; set; }
public virtual ICollection<HistricAddress> HistoricAddresses { get; set; }
...
}
and various other ways, but this also throws up errors. There must be a proper way of doing this. The last error I got was:
"System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.InvalidOperationException: A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'ID'."
You can map the following model with 3 tables.
public class user
{
public virtual int ID { get; set; }
...
public virtual int? AddressId { get; set; }
public virtual Address CurrentAddress { get; set; }
public virtual ICollection<Address> HistoricAddresses { get; set; }
}
public class Address
{
public virtual int ID { get; set; }
public virtual ICollection<User> Users { get; set; }
...
}
Override the OnModelCreating
method of your custom DbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasOptional(user => user.CurrentAddress).WithMany()
.HasForeignKey(user => user.AddressId);
modelBuilder.Entity<User>()
.HasMany(user => user.HistoricAddresses)
.WithMany(address => address.Users)
.Map(m =>
{
m.ToTable("UserAddresses");
m.MapLeftKey("UserId");
m.MapRightKey("AddressId");
});
}
Tables created are