简体   繁体   中英

EF Core connect Entity to View. One to Many

I have simple project to show the problem, I want to connect ICollection<Post> with view View_BlogPosts . This is just simplified scenario, in real live i need to connect entity with big View with many columns from different tables.

The most interesting part of code is: OnModelCreating(ModelBuilder modelBuilder) where there is configuration View with Entity: Post (One Blog to Many Posts). But its not working now, this line of code: var test = db.BlogWithPosts.ToList(); returns empty collection of Posts. 在此处输入图像描述

How to fix this?

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace Samples
{
    public class Program
    {
        private static void Main()
        {
            SetupDatabase();

            using (var db = new BloggingContext())
            {
                var test = db.BlogWithPosts.ToList();
            }
        }

        private static void SetupDatabase()
        {
            using (var db = new BloggingContext())
            {
                if (db.Database.EnsureCreated())
                {
                    db.Blogs.Add(
                        new Blog
                        {
                            Name = "Fish Blog",
                            Url = "http://sample.com/blogs/fish",
                            Posts = new List<Post>
                            {
                                new Post { Title = "Fish care 101" },
                                new Post { Title = "Caring for tropical fish" },
                                new Post { Title = "Types of ornamental fish" }
                            }
                        });

                    db.Blogs.Add(
                        new Blog
                        {
                            Name = "Cats Blog",
                            Url = "http://sample.com/blogs/cats",
                            Posts = new List<Post>
                            {
                                new Post { Title = "Cat care 101" },
                                new Post { Title = "Caring for tropical cats" },
                                new Post { Title = "Types of ornamental cats" }
                            }
                        });

                    db.Blogs.Add(
                        new Blog
                        {
                            Name = "Catfish Blog",
                            Url = "http://sample.com/blogs/catfish",
                            Posts = new List<Post>
                            {
                                new Post { Title = "Catfish care 101" }, new Post { Title = "History of the catfish name" }
                            }
                        });

                    db.SaveChanges();

                    db.Database.ExecuteSqlRaw(
                     @"CREATE VIEW View_BlogPosts AS
                            SELECT b.Name , b.BlogId, b.Url FROM Blogs b");
                }
            }
        }
    }

    public class BloggingContext : DbContext
    {
        private static readonly ILoggerFactory _loggerFactory
            = LoggerFactory.Create(
                builder => builder.AddConsole().AddFilter((c, l) => l == LogLevel.Information && !c.EndsWith("Connection")));

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

        public DbSet<BlogWithPosts> BlogWithPosts { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseSqlServer(
                   // @"Server=(localdb)\mssqllocaldb;Database=Sample.KeylessEntityTypes;Trusted_Connection=True;ConnectRetryCount=0;")
                   @"Server=.\SQLEXPRESS;Database=test_view;Trusted_Connection=True;")
                .UseLoggerFactory(_loggerFactory);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<BlogWithPosts>(eb =>
            {
                //eb.HasNoKey();
                eb.ToView("View_BlogPosts");
                eb.HasKey(bwp => bwp.BlogId);
                eb.Property(v => v.BlogName).HasColumnName("Name");

                eb
                .HasMany(bwp => bwp.Posts)
                .WithOne()
                .HasForeignKey(p => p.BlogId);
            });
        }
    }
   
    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }
        public string Url { get; set; }
        public ICollection<Post> Posts { get; set; }
    }

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

    public class BlogWithPosts
    {
        public int BlogId { get; set; }
        public string BlogName { get; set; }
        public ICollection<Post> Posts { get; set; } = new List<Post>();
    }
}

EDIT:
Thanks @Neil W for answer:

It is good point but after var test = db.BlogWithPosts.Include(bwp => bwp.Posts).ToList(); there is still no Posts.

I have checked Database after run program and in Post table I find out, that there is second Id added: BlogId1 在此处输入图像描述

I have filled BlogId column same as BlogId1 like this: 在此处输入图像描述 and posts appeared

But how to set configuration that second id: BlogId1 will not appear.

You need to ask for the related entities when accessing the context, using Include:

var test = db.BlogWithPosts.Include(bwp => bwp.Posts).ToList();

Thanks for all answers and comments. As @atiyar point there should be explicitly relation between Post and Blog which stops creating BlogId1 column. So working example is like below:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace Samples
{
    public class Program
    {
        private static void Main()
        {
            SetupDatabase();

            using (var db = new BloggingContext())
            {

                var test = db.BlogWithPosts.Include(bp => bp.Posts).ToList();
            }
        }

        private static void SetupDatabase()
        {
            using (var db = new BloggingContext())
            {
                if (db.Database.EnsureCreated())
                {
                    db.Blogs.Add(
                        new Blog
                        {
                            Name = "Fish Blog",
                            Url = "http://sample.com/blogs/fish",
                            Posts = new List<Post>
                            {
                                new Post { Title = "Fish care 101" },
                                new Post { Title = "Caring for tropical fish" },
                                new Post { Title = "Types of ornamental fish" }
                            }
                        });

                    db.Blogs.Add(
                        new Blog
                        {
                            Name = "Cats Blog",
                            Url = "http://sample.com/blogs/cats",
                            Posts = new List<Post>
                            {
                                new Post { Title = "Cat care 101" },
                                new Post { Title = "Caring for tropical cats" },
                                new Post { Title = "Types of ornamental cats" }
                            }
                        });

                    db.Blogs.Add(
                        new Blog
                        {
                            Name = "Catfish Blog",
                            Url = "http://sample.com/blogs/catfish",
                            Posts = new List<Post>
                            {
                                new Post { Title = "Catfish care 101" }, new Post { Title = "History of the catfish name" }
                            }
                        });

                    db.SaveChanges();

                    db.Database.ExecuteSqlRaw(
                     @"CREATE VIEW View_BlogPosts AS
                            SELECT b.Name , b.BlogId, b.Url FROM Blogs b");
                }
            }
        }
    }

    public class BloggingContext : DbContext
    {
        private static readonly ILoggerFactory _loggerFactory
            = LoggerFactory.Create(
                builder => builder.AddConsole().AddFilter((c, l) => l == LogLevel.Information && !c.EndsWith("Connection")));

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

        public DbSet<BlogWithPosts> BlogWithPosts { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseSqlServer(
                   // @"Server=(localdb)\mssqllocaldb;Database=Sample.KeylessEntityTypes;Trusted_Connection=True;ConnectRetryCount=0;")
                   @"Server=.\SQLEXPRESS;Database=test_view;Trusted_Connection=True;")
                .UseLoggerFactory(_loggerFactory);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<BlogWithPosts>(eb =>
            {
                //eb.HasNoKey();
                eb.ToView("View_BlogPosts");
                eb.HasKey(bwp => bwp.BlogId);
                eb.Property(v => v.BlogName).HasColumnName("Name");

                eb
                .HasMany(bwp => bwp.Posts)
                .WithOne()
                .HasForeignKey(p => p.BlogId);
            });

            modelBuilder.Entity<Blog>(blog =>
            {
                blog.HasMany(bwp => bwp.Posts)
                .WithOne(b => b.Blog)
                .HasForeignKey(p => p.BlogId);
            });
        }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }
        public string Url { get; set; }
        public ICollection<Post> Posts { get; set; }
    }

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

    public class BlogWithPosts
    {
        public int BlogId { get; set; }
        public string BlogName { get; set; }
        public ICollection<Post> Posts { get; set; } = new List<Post>();
    }
}

What is important this example was tested on EF Core 5.0.2

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