How can I use EF Code First to declare a one-to-many relationship?
I think this object model is what you are looking for:
public class Team
{
public int TeamId { get; set; }
public ICollection<Player> TeamMembers { get; set; }
public Player CreatedBy { get; set; }
}
public class Player
{
public int PlayerId { get; set; }
public Team Team { get; set; }
}
public class Context : DbContext
{
public DbSet<Player> Players { get; set; }
public DbSet<Team> Teams { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Player>()
.HasOptional(p => p.Team)
.WithMany(t => t.TeamMembers)
.Map(c => c.MapKey("TeamId"));
// Or alternatively you could start from the Team object:
modelBuilder.Entity<Team>()
.HasMany(t => t.TeamMembers)
.WithOptional(p => p.Team)
.Map(c => c.MapKey("TeamId"));
}
}
BTW, the following fluent API code that you are using is not correct:
...HasOptional(x => x.TeamMembers)
Because TeamMembers is a collection and cannot be used by HasOptional method which always has to be invoked with a single object.
Update - HasRequired vs. HasOptional:
While they both set up an association, they deliver slightly different results and have different requirements:
If it's a FK association (the FK property is exposed on the dependent object) then it must be a nullable type when using HasOptional and non-nullable type when using HasRequired or Code First will throw.
Code First will automatically switch cascade deletes on when using HasRequired method.
The other difference is the EF runtime behavior when it comes to deletion. Consider a scenario where we want to delete the principal object (e.g.
Team
) while it has a dependent object (e.g.Player
) and cascade delete is switched off. With HasOptional EF runtime will silently update the dependent FK column to null while with HasRequired EF will throw and ask you to either explicitly remove the dependent object or relate it to another principal object (If you want to try this you should be aware that in both cases both principal and dependent objects must be already loaded in context so that EF will have a track of them).
I've been able to get this to work automatically simply by doing something like this:
public class Team {
public int TeamId { get; set; }
...
public virtual ICollection<Player> Players { get; set; }
}
But you'll have to be more specifical about what exactly you mean when you say "doesn't work". What doesn't work, exactly? Are you getting an error message? If so, what is it? Is the Team property of the Player object always returning null?