简体   繁体   English

实体框架核心多对多关系未从数据库加载

[英]Entity Framework Core Many-to-Many Relationship not loading from database

Ok, so I followed the 'Many-to-many' example for Entity Framework Core: Relationships (at the end of the page). 好的,所以我遵循了“实体框架核心: 关系 ”的“多对多”示例(在页面末尾)。

It seems that when the database is initially created (createNew set to true) everything is working as expected but when I use an existing database (createNew set to false) the joins are no longer there. 似乎最初创建数据库时(createNew设置为true),一切都按预期工作,但是当我使用现有数据库(createNew设置为false)时,联接不再存在。 Following is a Console App showing the problem that I'm having: 以下是一个控制台应用程序,显示了我遇到的问题:

Output for createNew = true: createNew = true的输出:

Author 1 has written: - Book 1 - Book 2 作者1写道:-书1-书2

Author 2 has written: - Book 1 - Book 2 作者2写道:-书1-书2

Author 3 has written: - Book 4 作者3写道:-书4

Auhtor 4 has written: no books yet Auhtor 4写道:尚无书籍

Output for createNew = false: createNew = false的输出:

Author 1 has written: no books yet 作者1写道:尚无书籍

Author 2 has written: no books yet 作者2写道:还没有书

Author 3 has written: no books yet 作者3写道:还没有书

Auhtor 4 has written: no books yet Auhtor 4写道:尚无书籍

// Visual Studio 2017
// Console App (.NET Core)
// Nuget: Microsoft.EntityFrameworkCore.SqlServer

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

namespace ConsoleAppCoreEFMany
{
    /* 
    An Author can write several Books, and a Book can be written by several Authors..
    https://en.wikipedia.org/wiki/Many-to-many_(data_model)
    */

    class Author
    {
        public long AuthorId { get; set; }
        public string Name { get; set; }

        public List<AuthorBook> AuthorBook { get; set; }        
    }

    class Book
    {
        public long BookId { get; set; }
        public string Title { get; set; }

        public List<AuthorBook> AuthorBook { get; set; }
    }   

    class AuthorBook
    {
        public long AuthorId { get; set; }
        public Author Author { get; set; }

        public long BookId { get; set; }
        public Book Book { get; set; }
    }  

    class MyDbContext : DbContext
    {        
        public DbSet<Author> Author { get; set; }
        public DbSet<Book> Book { get; set; }        
        public DbSet<AuthorBook> AuthorBook { get; set; }        

        string connectionString = "";

        public MyDbContext(string connectionString, bool createNew)
        {
            this.connectionString = connectionString;

            if (createNew)
            {
                Database.EnsureDeleted();
                Database.EnsureCreated();
            }

            // to see the actual tables created add a Data Connection in View / Server Explorer, Data Source: (Microsoft SQL Server Database File), Browse: C:/Users/<user>/*.mdf (in this case TestEFManyMany.mdf)
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(connectionString);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<AuthorBook>()
                .HasKey(x => new { x.AuthorId, x.BookId }); // creates a composite key

            modelBuilder.Entity<AuthorBook>()
                .HasOne(x => x.Author)
                .WithMany(x => x.AuthorBook)
                .HasForeignKey(x => x.AuthorId);

            modelBuilder.Entity<AuthorBook>()
                .HasOne(x => x.Book)
                .WithMany(x => x.AuthorBook)
                .HasForeignKey(x => x.BookId);           
        }
    }

    class Program
    {


        static void Main(string[] args)
        {
            bool createNew = false;

            using (var db = new MyDbContext("Server=(localdb)\\mssqllocaldb;Database=TestEFManyMany;Trusted_Connection=True;MultipleActiveResultSets=True", createNew))
            {
                try
                {
                    if (createNew)
                    {
                        // creating some 'unlinked' books
                        var book1 = new Book { Title = "Book 1" };
                        var book2 = new Book { Title = "Book 2" };
                        var book3 = new Book { Title = "Book 3" };

                        db.Book.Add(book1);
                        db.Book.Add(book2);
                        db.Book.Add(book3);
                        db.SaveChanges();

                        // creating some 'unlinked' authors
                        var author1 = new Author { Name = "Author 1" };
                        var author2 = new Author { Name = "Author 2" };

                        db.Author.Add(author1);
                        db.Author.Add(author2);
                        db.SaveChanges();

                        // link authors and books

                        // Author 1 and Author 2 have written Book 1
                        db.AuthorBook.Add(new AuthorBook { AuthorId = author1.AuthorId, BookId = book1.BookId });
                        db.AuthorBook.Add(new AuthorBook { AuthorId = author2.AuthorId, BookId = book1.BookId });

                        db.SaveChanges();

                        // Author 2 also has written Book 2
                        db.AuthorBook.Add(new AuthorBook { AuthorId = author2.AuthorId, BookId = book2.BookId });

                        // creating initially linked 
                        db.AuthorBook.Add(new AuthorBook
                        {
                            Author = new Author { Name = "Author 3" },
                            Book = new Book { Title = "Book 4" }
                        });

                        db.SaveChanges();

                        // check if link between author 2 and book 1 exists
                        if (db.AuthorBook.Where(x => x.AuthorId == author2.AuthorId && x.BookId == book1.BookId).Count() == 0)
                        {
                            db.AuthorBook.Add(new AuthorBook { AuthorId = author2.AuthorId, BookId = book1.BookId });
                        }

                        // check if link between author 1 and book 2 exists
                        if (db.AuthorBook.Where(x => x.AuthorId == author1.AuthorId && x.BookId == book2.BookId).Count() == 0)
                        {
                            db.AuthorBook.Add(new AuthorBook { AuthorId = author1.AuthorId, BookId = book2.BookId });
                        }

                        db.SaveChanges();

                        var author4 = new Author { Name = "Auhtor 4" };
                        db.Author.Add(author4);
                        db.SaveChanges();                       
                    }


                    foreach (var author in db.Author)
                    {
                        Console.WriteLine(author.Name + " has written:");

                        if (author.AuthorBook != null)
                        {
                            var books = author.AuthorBook.Select(x => x.Book).ToList();

                            foreach (var book in books)
                            {
                                Console.WriteLine("- " + book.Title);
                            }                            
                        }
                        else
                        {
                            Console.WriteLine(" no books yet");
                        }

                        Console.WriteLine();
                    }                   
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                }                
            }

            Console.ReadKey();
        }
    }
}

Data tables: 数据表:

在此处输入图片说明

I sure hope I did something really wrong and it's not a bug.. 我当然希望我做错了什么,但这不是错误。

Latest EF does not support automatic lazy-loading. 最新的EF不支持自动延迟加载。 You can read more and track this task here. 您可以在此处阅读更多内容并跟踪此任务

EF team stated, that they have not yet decided whether automatic lazy-loading will be included in upcoming updates. EF团队表示,他们尚未决定是否在即将进行的更新中包括自动延迟加载。

To answer your question you need to manually load relational data . 要回答您的问题,您需要手动加载关系数据 To do so you might want to use Include and ThenInclude methods provided by EF Core. 为此,您可能要使用EF Core提供的IncludeThenInclude方法。

Example: 例:

 ctx.EntityOne
    .Include(eOne => eOne.EntityTwo)
    .ThenInclude(eTwo => eTwo.SomeOtherEntity)
    .Where(entityOne => YourQuery);

This code snipped will load relational links between these entities as it was done in previous EF versions automatically. 像在以前的EF版本中一样,该代码片段将自动加载这些实体之间的关系链接。

Ok Ivan Stoev pointed me in the right direction: Loading Related Data 好的,伊万·斯托夫(Ivan Stoev)向我指出了正确的方向: 加载相关数据

According to the Tip on Eager loading: 根据急切加载提示:

Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. 实体框架核心将自动将导航属性修复为先前加载到上下文实例中的任何其他实体。 So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded. 因此,即使您未明确包含导航属性的数据,如果先前已加载了某些或所有相关实体,也可能仍会填充该属性。

So it is enough to put var eagerLoading = db.AuthorBook.Include(x => x.Author).Include(x => x.Book).ToList(); 因此,只需将var eagerLoading = db.AuthorBook.Include(x => x.Author).Include(x => x.Book).ToList(); in front of the loop within the context (notice you have to use the join table in order to include both, Author and Book, also ToList() is necessary) 在上下文中循环的前面(注意,您必须使用联接表才能同时包含Author和Book,还必须使用ToList())

var eagerLoading = db.AuthorBook.Include(x => x.Author).Include(x => x.Book).ToList();

foreach (var author in db.Author)
{
    Console.WriteLine(author.Name + " has written:");

    if (author.AuthorBook != null)
    {
        var books = author.AuthorBook.Select(x => x.Book).ToList();

        foreach (var book in books)
        {
            Console.WriteLine("- " + book.Title);
        }
    }
    else
    {
        Console.WriteLine(" no books yet");
    }

    Console.WriteLine();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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