0

Using Microsoft.EntityFrameworkCore.InMemory (5.0.0), I have the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using BlogExample;

namespace BlogExample.Data
{
    public class BlogsContext : DbContext
    {
        public BlogsContext (DbContextOptions<BlogsContext> options)
            : base(options)
        {
        }

        public DbSet<BlogExample.Blog> Blogs { get; set; }
        public DbSet<BlogExample.Post> Posts { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>()
                .HasMany(b => b.Posts)
                .WithOne();

            modelBuilder.Entity<Blog>()
                .Navigation(b => b.Posts)
                    .UsePropertyAccessMode(PropertyAccessMode.Property);
        }
    }
}
namespace BlogExample
{
    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; }
    }
}

Now I have the following controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using BlogExample;
using BlogExample.Data;

namespace BlogExample.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BlogsController : ControllerBase
    {
        private readonly BlogsContext _context;

        public BlogsController(BlogsContext context)
        {
            _context = context;
        }

        // GET: api/Blogs
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Blog>>> GetBlog()
        {
            return await _context.Blogs.ToListAsync();
        }

        // GET: api/Blogs/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Blog>> GetBlog(int id)
        {
            var blog = await _context.Blogs.FindAsync(id);

            if (blog == null)
            {
                return NotFound();
            }

            return blog;
        }

        // POST: api/Blogs
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPost]
        public async Task<ActionResult<Blog>> PostBlog(Blog blog)
        {
            _context.Blogs.Add(blog);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetBlog", new { id = blog.BlogId }, blog);
        }
    }
}

So, when I POST the following JSON for a blog:

{
  "blogId": 1,
  "url": "MyUrl",
  "posts": [
    {
      "postId": 1,
      "title": "title1",
      "content": "content1"
    }
  ]
}

Then if I try to perform the GET call to get all my Blogs, I get the blog I just entered above with the posts list property set to null as shown in the response body below:

[
  {
    "blogId": 1,
    "url": "MyUrl",
    "posts": null
  }
]

My code can be found here

I am using the following documentation as a reference:

https://learn.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key#single-navigation-property-1

4
  • 1
    I cloned your repo and it worked fine. Add a Posts controller and you'll see that after POSTing the blog you can GET the Posts. Commented Nov 25, 2020 at 22:05
  • Yes, I can GET the Posts, but when I GET my Blogs, I still get a null in the posts property of the returned Blog. But now I think I know where to look now. This behavior made it clear that my DbContext is working. I am just doing something wrong when retrieving the data. Commented Nov 25, 2020 at 22:17
  • 1
    You must request EF to load related entities. Read: learn.microsoft.com/en-us/ef/core/querying/related-data/eager Commented Nov 25, 2020 at 22:26
  • Yes. that fixed it. I just added .Include(blog => blog.Posts). Thank you very much! I really can't thank you enough! Can we put your last comment as an answer to this question? Commented Nov 25, 2020 at 22:32

1 Answer 1

1

You need to request that EF include related entities. Otherwise fetching a single Entity could end up bringing the whole database back.

Should be

// GET: api/Blogs
[HttpGet]
public async Task<ActionResult<IEnumerable<Blog>>> GetBlogs()
{
    return await _context.Blogs
                         .Include(blog => blog.Posts)
                         .ToListAsync();
}

See

Eager loading

You can use the Include method to specify related data to be included in query results. In the following example, the blogs that are returned in the results will have their Posts property populated with the related posts.

Eager Loading of Related Data

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.