简体   繁体   中英

Entity Framework Core: model is populated incorrectly

I'm new to EF Core, and using this tutorial I've got an unexpected result, namely, the data looks normal in the model when it's just populated, but in a new instance of the context, the navigation property in the principal entity is not populated, and the navigation property in the dependent entity is populated in a peculiar way.

Here is the model (the code from the tutorial is slightly modified):

using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace EFGetStarted
{
    public class BloggingContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder options)
        {
            options.UseSqlite("Data Source=blogging.db");
        }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }
        public List<Post> Posts { get; } = new List<Post>();

        public override string ToString()
        {
            return
                "{" +
                "BlogId: " + BlogId + ", " +
                "Name: " + Name + ", " +
                "Posts.Count: " + Posts.Count +
                "}";
        }
    }

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

        public override string ToString()
        {
            return
                "{" + 
                "PostId: " + PostId + ", " +
                "Content: " + Content + ", " +
                "BlogId: " + BlogId + 
                "}";
        }
    }
}

And here is the program:

using static System.Console;

namespace EFGetStarted
{
    class Program
    {
        static void Main()
        {
            CreateContents(new BloggingContext());
            Print(new BloggingContext());
        }

        static void CreateContents(BloggingContext db)
        {
            AddBlog(db);
            Print(db);
        }

        private static void AddBlog(BloggingContext db)
        {
            var blog = new Blog { Name = "Blog 1" };
            db.Add(blog);

            blog.Posts.Add(new Post { Content = "Post 1" });
            blog.Posts.Add(new Post { Content = "Post 2" });
            blog.Posts.Add(new Post { Content = "Post 3" });

            db.SaveChanges();
        }

        private static void Print(BloggingContext db)
        {
            PrintBlogs(db);
            PrintPosts(db);
        }

        private static void PrintBlogs(BloggingContext db)
        {
            WriteLine("---- Blogs: ----");
            foreach (var blog in db.Blogs) Print(blog);
            WriteLine("");
        }

        private static void PrintPosts(BloggingContext db)
        {
            WriteLine("---- Posts: ----");
            foreach (var post in db.Posts) Print(post);
            WriteLine("");
        }

        private static void Print(Blog blog)
        {
            WriteLine(blog);
            foreach (var post in blog.Posts) WriteLine(post);
            WriteLine();
        }

        private static void Print(Post post)
        {
            WriteLine(post);
            WriteLine(post.Blog);
            foreach (var blogPost in post.Blog.Posts) WriteLine(blogPost);
            WriteLine();
        }
    }
}

The program produces the following output:

---- Blogs: ----
{BlogId: 1, Name: 'Blog 1', Posts.Count: 3}
{PostId: 1, Content: 'Post 1', BlogId: 1}
{PostId: 2, Content: 'Post 2', BlogId: 1}
{PostId: 3, Content: 'Post 3', BlogId: 1}


---- Posts: ----
{PostId: 1, Content: 'Post 1', BlogId: 1}
{BlogId: 1, Name: 'Blog 1', Posts.Count: 3}
{PostId: 1, Content: 'Post 1', BlogId: 1}
{PostId: 2, Content: 'Post 2', BlogId: 1}
{PostId: 3, Content: 'Post 3', BlogId: 1}

{PostId: 2, Content: 'Post 2', BlogId: 1}
{BlogId: 1, Name: 'Blog 1', Posts.Count: 3}
{PostId: 1, Content: 'Post 1', BlogId: 1}
{PostId: 2, Content: 'Post 2', BlogId: 1}
{PostId: 3, Content: 'Post 3', BlogId: 1}

{PostId: 3, Content: 'Post 3', BlogId: 1}
{BlogId: 1, Name: 'Blog 1', Posts.Count: 3}
{PostId: 1, Content: 'Post 1', BlogId: 1}
{PostId: 2, Content: 'Post 2', BlogId: 1}
{PostId: 3, Content: 'Post 3', BlogId: 1}


---- Blogs: ----
{BlogId: 1, Name: 'Blog 1', Posts.Count: 0}


---- Posts: ----
{PostId: 1, Content: 'Post 1', BlogId: 1}
{BlogId: 1, Name: 'Blog 1', Posts.Count: 1}
{PostId: 1, Content: 'Post 1', BlogId: 1}

{PostId: 2, Content: 'Post 2', BlogId: 1}
{BlogId: 1, Name: 'Blog 1', Posts.Count: 2}
{PostId: 1, Content: 'Post 1', BlogId: 1}
{PostId: 2, Content: 'Post 2', BlogId: 1}

{PostId: 3, Content: 'Post 3', BlogId: 1}
{BlogId: 1, Name: 'Blog 1', Posts.Count: 3}
{PostId: 1, Content: 'Post 1', BlogId: 1}
{PostId: 2, Content: 'Post 2', BlogId: 1}
{PostId: 3, Content: 'Post 3', BlogId: 1}

As you can see, when the model is created, the blog has three posts, and every post references the blog with the same three posts.

When printed using a new instance of the context, the blog has zero posts and, looks like, posts reference different instances of the blog each with a different number of associated posts.

How to make the model in the new instance of the context look like the one in which it was populated?

There is a bug in the code. Code doesn't have include statement, this is why you can't see posts. Try this:

private static void PrintBlogs(BloggingContext db)
        {
          
            var blogs = db.Blogs.Include(i => i.Posts).ToArray();

            WriteLine("---- Blogs: ----");
            foreach (var blog in blogs) Print(blog);
            WriteLine("");
        }

        private static void PrintPosts(BloggingContext db)
        {
            var posts = db.Posts.Include(i => i.Blog).ToArray();

            WriteLine("---- Posts: ----");
            foreach (var post in posts) Print(post);
            WriteLine("");
        }

Now the result is:


---- Blogs: ----
{BlogId: 1, Name: Blog 1, Posts.Count: 3}
{PostId: 1, Content: Post 1, BlogId: 1}
{PostId: 2, Content: Post 2, BlogId: 1}
{PostId: 3, Content: Post 3, BlogId: 1}


---- Posts: ----
{PostId: 1, Content: Post 1, BlogId: 1}
{BlogId: 1, Name: Blog 1, Posts.Count: 3}
{PostId: 1, Content: Post 1, BlogId: 1}
{PostId: 2, Content: Post 2, BlogId: 1}
{PostId: 3, Content: Post 3, BlogId: 1}

{PostId: 2, Content: Post 2, BlogId: 1}
{BlogId: 1, Name: Blog 1, Posts.Count: 3}
{PostId: 1, Content: Post 1, BlogId: 1}
{PostId: 2, Content: Post 2, BlogId: 1}
{PostId: 3, Content: Post 3, BlogId: 1}

{PostId: 3, Content: Post 3, BlogId: 1}
{BlogId: 1, Name: Blog 1, Posts.Count: 3}
{PostId: 1, Content: Post 1, BlogId: 1}
{PostId: 2, Content: Post 2, BlogId: 1}
{PostId: 3, Content: Post 3, BlogId: 1}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM