简体   繁体   English

Entity Framework Core 无法更新包含相关对象的 object

[英]Entity Framework Core fail to update object with related objects included

I am trying to implement a WebApi with Entity Framework Core.我正在尝试使用 Entity Framework Core 实现 WebApi。 I have modelled an implicit many-to-many relationship , and scaffolded the controllers based on the DbContext.我已经建模了一个隐式的多对多关系,并基于DbContext搭建了控制器。

But this does not allow persisting an object with it's linked objects.但这不允许将 object 与其链接对象保持一致。

A simplified version demonstrating my problem:演示我的问题的简化版本:

using Microsoft.EntityFrameworkCore;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;

namespace Tests
{
    public class Author
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public ICollection<Book> Books { get; set; }
    }

    public class Book
    {
        public long Id { get; set; }
        public string Title { get; set; }
        public ICollection<Author> Authors { get; set; }
    }

    public class LibraryDbContext : DbContext
    {
        public DbSet<Book> Books { get; set; }
        public DbSet<Author> Authors { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Server=localhost\mssqlserver01;Database=Library;Trusted_Connection=True;MultipleActiveResultSets=true");
        }
    }

    [TestClass]
    public class Test
    {
        [TestMethod]
        public void TestMethod1()
        {
            // Assign
            Author author_buzz = new Author()
            {
                Name = "Buzz",
                Books = new List<Book>()
                {
                    new Book()
                    {
                        Title = "Book 1",
                    },
                    new Book()
                    {
                        Title = "Book 2",
                    }
                }
            };

            using (LibraryDbContext context = new LibraryDbContext())
            {
                context.Database.EnsureDeleted();
                context.Database.EnsureCreated();

                context.Authors.Add(author_buzz);
                context.SaveChanges();
            }

            // Act
            author_buzz.Name = "Buzz Lightyear";
            //author_buzz.Books = null; // Uncommenting this will make the test pass.

            using (LibraryDbContext context = new LibraryDbContext())
            {
                context.Entry(author_buzz).State = EntityState.Modified;
                //context.Update(author_buzz); // Using this way of updating doesn't work either.

                context.SaveChanges();
            }

            // Assert
            using (LibraryDbContext context = new LibraryDbContext())
            {
                author_buzz = context.Authors
                    .Include(author => author.Books)
                    .Single();

                Assert.AreEqual("Buzz Lightyear", author_buzz.Name);
                Assert.AreEqual(2, author_buzz.Books.Count);
            }
        }
    }
}

Running this test results in the following exception on the last SaveChanges():在最后一个 SaveChanges() 上运行此测试会导致以下异常:

SqlException: Violation of PRIMARY KEY constraint 'PK_AuthorBook'. SqlException:违反主键约束“PK_AuthorBook”。 Cannot insert duplicate key in object 'dbo.AuthorBook'.无法在 object 'dbo.AuthorBook' 中插入重复密钥。 The duplicate key value is (1, 1).重复键值为 (1, 1)。

However, when I set the property Books to null, the test passes.但是,当我将属性 Books 设置为 null 时,测试通过了。

It seems to me that Entity Framework does not recognize the fact that the relationship between the author and the books is an existing one, and tries to add it again.在我看来,Entity Framework 并没有认识到作者和书籍之间的关系是现有关系这一事实,并试图再次添加它。 Then it fails because that link already exists in the entity AuthorBook.然后它会失败,因为该链接已经存在于实体 AuthorBook 中。

How can I update an entity, without clearing it's relationship properties?如何在不清除其关系属性的情况下更新实体? In a more complex domain, this is something that I don't want to go trough, and I feel there should be an easier way.在更复杂的领域,这是我不想 go 低谷的东西,我觉得应该有更简单的方法。

(This is the same implementation as the PUT method in the controller that is scaffolded by visual studio, based on Entity Framework. Also, using context.Update() instead doesn't seem to work either.) (这与 Visual Studio 基于实体框架搭建的 controller 中的 PUT 方法的实现相同。此外,使用 context.Update() 似乎也不起作用。)

The problem was that the entity was not attached to the context anymore.问题是实体不再附加到上下文中。 Solved it by calling context.Attach(author_buzz);通过调用context.Attach(author_buzz);解决了它before setting the State to Modified.在将 State 设置为已修改之前。

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

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