user326502 user326502 - 3 months ago 33
C# Question

Entity Framework 5 Code First Self-Referencing Relationship

How would I map the following relationship in Entity Framework 5?

public class Item {
public int Id { get; set; }
public int? ParentItemId { get; set; }
public string Value { get; set; }

public Item ParentItem { get; set; }
public List<Item> ChildItems { get; set; }
}


I've tried this:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);

modelBuilder.Entity<Item>()
.HasOptional(i => i.ParentItem)
.WithMany(i => i.ChildItems)
.HasForeignKey(i => i.ParentItemId);
}


and this:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);

modelBuilder.Entity<Item>()
.HasMany(i => i.ChildItems)
.WithOptional(i => i.ParentItem)
.HasForeignKey(i => i.ParentItemId);
}


which both result in this error:

The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role.

If I start with database-first mapping, here is what the generated entity looks like:

public partial class Item
{
public Item()
{
this.ChildItems = new HashSet<Item>();
}

public int Id { get; set; }
public Nullable<int> ParentItemId { get; set; }
public string Value { get; set; }

public virtual ICollection<Item> ChildItems { get; set; }
public virtual Item ParentItem { get; set; }
}


I know this will work if I start with db-first, I just need to know how to define the relationship in code-first.

Answer

The exception means the following:

  • "types of all properties in the Dependent Role" are the types of the FK property which is ParentItemId and has type int? in your model
  • "corresponding property types in the Principal Role" are the types of the PK property which is Id and has type int in your model

They are the same (nullability doesn't matter). However, the exception says, they are not.

The exception normally would only occur if the types don't match, for example if you had a long (or any other type) for the PK and an int? for the FK.

Comments