How to work with collections

c# entity-framework entity-framework-core

Question

Can anyone write mini-guide which explains how to work with collections in EF?

For example I have following models:

public class BlogPost
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime DateTime { get; set; }
    public List<PostComment> Comments { get; set; }
}

public class PostComment
{
    public int Id { get; set; }
    public BlogPost ParentPost { get; set; }
    public string Content { get; set; }
    public DateTime DateTime { get; set; }
}

And context class:

public class PostContext : DbContext
{
    public DbSet<BlogPost> Posts { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Posts;Trusted_Connection=True;MultipleActiveResultSets=true");

    }
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

    }
}

What do I need to write in OnModelCreating method so that I can use Posts.Add and etc. everywhere in my code?

Accepted Answer

Here are my tips for working with navigation properties in Entity Framework Core.

Tip 1: Initialize collections

class Post
{
    public int Id { get; set; }

    // Initialize to prevent NullReferenceException
    public ICollection<Comment> Comments { get; } = new List<Comment>();
}

class Comment
{
    public int Id { get; set; }
    public string User { get; set; }

    public int PostId { get; set; }
    public Post Post { get; set; }        
}

Tip 2: Build using the HasOne and WithMany or HasMany and WithOne methods

protected override void OnModelCreating(ModelBuilder model)
{
    model.Entity<Post>()
        .HasMany(p => p.Comments).WithOne(c => c.Post)
        .HasForeignKey(c => c.PostId);
}

Tip 3: Eagerly load the collection

var posts = db.Posts.Include(p => p.Comments);

Tip 4: Explicitly load if you didn't eagerly

db.Comments.Where(c => c.PostId == post.Id).Load();

Popular Answer

It seems that Commentsnavigation property does not works properly. Try to provide to BlogPost model the actual referencig field to PostComment table. Also rename the navigation property in PostComments for the EF naming compliance.

public class BlogPost
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime DateTime { get; set; }

    public int PosCommentId {get; set; }
    public List<PostComment> PostComments { get; set; }
}

If this neither works you have to define manually your relationship, but before help in this, you'd better provide the schema of this two tables in your db.

UPDATE 01:

First tip: You are using singular named tables. This is not compliant to EF naming convention. Pluralization has to be turned off. Just put this line in OnModelCreating method.

modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

Second tip: My previous advice was totally wrong do not consider it anymore, just use your old models schema. Now, assuming a one-to-many relationship between comment and post:

protected override void OnModelCreating(ModelBuilder builder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    modelBuilder.Entity<PostComment>().HasRequired<BlogPost>(c => c.ParentPost)
            .WithMany(p => p.Comments);

    base.OnModelCreating(builder);

}

For more INFOs :

EF one-to-many relationship tutorial

Relationship and navigation properties

Configuring Relationships with the Fluent API



Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow