The following is an simplified example of a parent/child relationship I'm trying to get working in Entity Framework code-first. The parent has a list of children, and one of them is selected as the default:
public class Parent
{
[Key]
public int Id { get; set; }
public virtual Child DefaultChild { get; set; } // One-to-One
public virtual ICollection<Child> Children { get; set; } // One-to-Many
}
public class Child
{
[Key]
public int Id { get; set; }
[Required]
public virtual Parent Parent { get; set; }
}
When I run entity framework's add-migration
command, it is setting the Id for Child as a key, however, instead of making it an IDENTITY
it is using a Foreign Key reference to the parent Id.
I tried doing the following on my DbContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>().HasOptional(p => p.DefaultChild).WithRequired(c => c.Parent);
modelBuilder.Entity<Parent>().HasMany(p => p.Children).WithRequired(c => c.Parent);
base.OnModelCreating(modelBuilder);
}
However, then it tosses this error: Schema specified is not valid. Errors: The relationship 'Sample.Presentation.DataAccess.Parent_DefaultChild' was not loaded because the type 'Sample.Presentation.DataAccess.Child' is not available.
How are you supposed to handle these relationships?
I know I could add a boolean flag to the Child (e.g. IsDefault
) and get rid of the DefaultChild relationship on the parent. However, I'd like to avoid that if possible.
Edit: I found this info on StackOverflow utilizing WithOptionalPrincipal
, however, it creates an additional ParentId field on the child as opposed to creating the ChildId on the parent?! Not quite what I want.
Edit: Added DatabaseGenerated
as suggested in comments. This is what the migrations output:
CreateTable(
"dbo.Children",
c => new
{
Id = c.Int(nullable: false, identity: true),
Parent_Id = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Parents", t => t.Id) // <== I don't want this!
.ForeignKey("dbo.Parents", t => t.Parent_Id, cascadeDelete: true)
.Index(t => t.Id)
.Index(t => t.Parent_Id);
CreateTable(
"dbo.Parents",
c => new
{
Id = c.Int(nullable: false, identity: true) // <== I expect DefaultChildId after this
})
.PrimaryKey(t => t.Id); // <== and a foreign key referencing Child.Id