Search code examples
c#entity-frameworkasp.net-core

EF core one-to-many relationships HasOne().WithMany() vs HasMany().WithOne()


Let's say I have the following 2 models:

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public Blog Blog { get; set; }
}

Now if I want to configure the models relationships in DbContext is there any difference between:

modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b.Posts);

and

modelBuilder.Entity<Blog>()
            .HasMany(b => b.Posts)
            .WithOne(p => p.blog);

and if there is a diffrence, what is it? should I write both or just one of them?

As a side note: Do I have to define foreign keys? Based on my knowledge about databases, you can't create relationships without foreign keys but EF doesn't require you to have foreign key fields. So how does EF handles relationships without knowing foreign keys? Does it cause performance drops or bugs?


Solution

  • You're right, you can create relations in DbContext without foreign keys in database.

    Also:

    WithOne: 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.

    Many-to-many: relationships without an entity class to represent the join table are not yet supported. However, you can represent a many-to-many relationship by including an entity class for the join table and mapping two separate one-to-many relationships.

    You only need to define one relation, because in some cases you'll create a relation for parent-child without navigation properties (one or collection).

    For your example: you add a relation for Blog -> Posts because you have navigation properties in both objects, the two lines make the same but in different way:

    • Blog -> Posts (Parent -> child)
    • Posts -> Blog (Child -> Parent)