(Entity Framework 6, .NET 4, VS 2010)
I have created a small Blog project to illustrate the problem. This is a Blog that has many posts but only one of the posts act as the main post.
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> PostEntities { get; set; }
public int? MainPostId { get; set; }
[ForeignKey("MainPostId")]
public virtual Post MainPostEntity { get; set; } // Problem here
}
public class Post
{
public int Id { get; set; }
public int BlogId { get; set; }
[ForeignKey("BlogId")]
public virtual Blog BlogEntity { get; set; }
public string Title { get; set; }
}
modelBuilder.Entity<Blog>()
.HasOptional(b => b.MainPostEntity)
.WithRequired(p => p.BlogEntity);
static void Main(string[] args)
{
Database.SetInitializer<EFTestContext>(null);
EFTestContext db = new EFTestContext();
Post[] posts = db.Posts.ToArray(); // Error here
}
If I remove the navigation property public virtual Post MainPostEntity
everything works as expected. However, when I add it, I get:
base {System.SystemException} = {"The ForeignKeyAttribute on property 'MainPostEntity' on type 'EFTest.Blog' is not valid. The foreign key name 'MainPostId' was not found on the dependent type 'EFTest.Post'. The Name value should be a comma separated list of foreign key property names."}
If I remove the fluent API call, I get {"Invalid column name 'Blog_Id'."}
If I change the attribute from [ForeignKey("MainPostId")]
to [ForeignKey("Id")]
I get the following error {"Invalid column name 'Blog_Id'."}
What am I doing wrong? How do I enable the navigation property from Blog to the Main Post?
We can configure a one-to-One relationship between entities using Fluent API where both ends are required, meaning that the Student entity object must include the StudentAddress entity object and the StudentAddress entity must include the Student entity object in order to save it.
One-to-one. One to one relationships have a reference navigation property on both sides. They follow the same conventions as one-to-many relationships, but a unique index is introduced on the foreign key property to ensure only one dependent is related to each principal.
The addition of a foreign key due to a one-to-one relationship can be made in either direction. One strategy is to maintain the most natural parent–child relationship by putting the parent key into the child table. Another strategy is based on efficiency: Add the foreign key to the table with fewer rows.
You can create such a relationship by defining a third table, called a junction table, whose primary key consists of the foreign keys from both table A and table B.
The problem you are having is that you're creating two relationships between the same two tables and EF can't distinguish which relationship the navigation property BlogEntity
is part of. Using the fluent api you can explicitly tell it so, the data annotations are then not needed.
modelBuilder.Entity<Blog>().HasMany(b => b.PostEntities).
WithRequired(p => p.BlogEntity).
HasForeignKey(p => p.BlogId).
WillCascadeOnDelete(true);
modelBuilder.Entity<Blog>().HasOptional(b => b.MainPostEntity).
WithMany().
HasForeignKey(b => b.MainPostId).
WillCascadeOnDelete(false);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With