Your original model in the question should work. You can test it quite easily:
- Create new console application (VS 2010)
- Name it "EFTestApp"
- Add reference to "EntityFramework.dll"
- Delete content of Program.cs and copy the following code into the file
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
namespace EFTestApp
{
public class User
{
public int Id { get; set; }
public int? DefaultAddressId { get; set; }
[ForeignKey("DefaultAddressId")]
public virtual Address DefaultAddress { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
public class Address
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Address> Addresses { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var context = new Context())
{
try
{
User user = new User() { Addresses = new List<Address>() };
Address address1 = new Address() { Name = "Address1" };
Address address2 = new Address() { Name = "Address2" };
user.Addresses.Add(address1);
user.Addresses.Add(address2);
context.Users.Add(user);
context.SaveChanges();
// user has now 2 addresses in the DB and no DefaultAddress
user.DefaultAddress = address1;
context.SaveChanges();
// user has now address1 as DefaultAddress
user.DefaultAddress = address2;
context.SaveChanges();
// user has now address2 as DefaultAddress
user.DefaultAddress = null;
context.SaveChanges();
// user has now no DefaultAddress again
}
catch (Exception e)
{
throw;
}
}
}
}
}
In SQL Server Express it creates a new DB called "EFTestApp.Context". You can set breakpoints on every SaveChanges above, step over and watch the changes in the DB.
If you look at the relationships in the database then there are two, and in table Addresses
in the DB is a foreign key column User_Id
.
I think you could also remove public int? DefaultAddressId { get; set; }
and [ForeignKey("DefaultAddressId")]
. It creates the same database tables and relationships with an optional DefaultAddress.
Perhaps you want the relationship Address -> User
as required (Addresses cannot live alone in the DB without a User). Then you can add this to the Context class:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasMany(u => u.Addresses)
.WithRequired();
}
It makes User_Id
in the Addresses table non nullable and sets up cascading delete by default. So, when a user gets deleted all its addresses get deleted as well.