【问题标题】:Why does EF Core inserts before deleting instead of deleting and then inserting when updating a child list of a model?为什么更新模型的子列表时 EF Core 在删除之前插入而不是删除然后插入?
【发布时间】:2020-08-06 13:14:47
【问题描述】:

我是 Entity Framework Core 3,我正在使用 Pomelo MySQL 提供程序。 我正在尝试使用以下内容更新子属性:

model.Items = collection;

其中model 是存在于数据库中的实体,collection 是要为该列表设置的新实体ICollection<Item>

然后当我运行时:

dbContext.Models.Update(model);
await dbContext.SaveChangesAsync(ct);

我注意到一个奇怪的行为(通过查看 EF Core 查询日志):以前存在的与模型关联的项目不会立即删除,而是只有在插入 collection 中的新项目后才会删除。

这会导致数据库出现完整性约束错误,因为在短时间内(在插入和稍后删除之间)某些唯一列存在重复值。

我想知道这种行为是否可以以某种方式配置,以及为什么只有在插入后才删除相关实体,而反之亦然。


如何重现

为了重现该问题,您可以使用此docker-compose.yml 文件来设置 MySQL 8 数据库:

version: '3.4'

services:

  database:
    image: mysql:8.0
    environment:
      MYSQL_USER: So61383388
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: So61383388
    ports:
      - "3306:3306"
      - "33060:33060"

然后运行这个程序:

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

namespace IssueConsoleTemplate
{
    public class IceCream
    {
        public int IceCreamId { get; set; }
        public string Name { get; set; }

        public ICollection<IceCreamVariation> Variations { get; set; } = new HashSet<IceCreamVariation>();
    }

    public class IceCreamVariation
    {
        public int IceCreamVariationId { get; set; }
        public string Name { get; set; }
        public int IceCreamId { get; set; }

        public IceCream IceCream { get; set; }

        public ICollection<IceCreamVariationQuality> Qualities { get; set; } = new HashSet<IceCreamVariationQuality>();
    }

    public class IceCreamVariationQuality
    {
        public int IceCreamVariationQualityId { get; set; }
        public string Name { get; set; }
        public int IceCreamVariationId { get; set; }

        public IceCreamVariation IceCreamVariation { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<IceCream> IceCreams { get; set; }
        public DbSet<IceCreamVariation> IceCreamVariations { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseMySql(
                    "server=127.0.0.1;port=3306;user=root;password=root;database=So61383388",
                    b => b.ServerVersion("8.0"))
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<IceCream>()
                .HasData(
                    new IceCream {IceCreamId = 1, Name = "Vanilla"}
                );

            modelBuilder.Entity<IceCreamVariation>()
                .HasData(
                    new IceCreamVariation {IceCreamVariationId = 1, Name = "Double Vanilla Bourbon", IceCreamId = 1},
                    new IceCreamVariation {IceCreamVariationId = 2, Name = "Vanilla Caramel", IceCreamId = 1}
                );

            modelBuilder.Entity<IceCreamVariationQuality>()
                .HasData(
                    new IceCreamVariationQuality {IceCreamVariationQualityId = 1, Name = "Fresh", IceCreamVariationId = 1},
                    new IceCreamVariationQuality {IceCreamVariationQualityId = 2, Name = "Yummy", IceCreamVariationId = 1},
                    new IceCreamVariationQuality {IceCreamVariationQualityId = 3, Name = "Woops", IceCreamVariationId = 2}
                );
        }
    }

    internal class Program
    {
        private static void Main()
        {
            using (var context = new Context())
            {
                context.Database.EnsureDeleted();
                context.Database.EnsureCreated();

                var iceCreamWithOldVariations = context.IceCreams
                    .Include(i => i.Variations)
                        .ThenInclude(i => i.Qualities)
                    .OrderBy(i => i.IceCreamId)
                    .FirstOrDefault();

                Debug.Assert(iceCreamWithOldVariations.Variations.Count == 2);

                var vanillaIceCream = iceCreamWithOldVariations;
                vanillaIceCream.Variations.Clear();
                vanillaIceCream.Variations.Add(
                    new IceCreamVariation 
                    {
                        Name = "Vanilla Cheesecake", 
                        Qualities = new IceCreamVariationQuality[]
                        {
                            new IceCreamVariationQuality { Name = "Healthy" },
                        },
                    });
                vanillaIceCream.Variations.Add(
                    new IceCreamVariation 
                    {
                        Name = "Vanilla Cheesecake", 
                        Qualities = new IceCreamVariationQuality[]
                        {
                            new IceCreamVariationQuality { Name = "Fresh" },
                            new IceCreamVariationQuality { Name = "Cool" },
                        },
                    });

                context.SaveChanges();

                var iceCreamWithNewVariations = context.IceCreams
                    .Include(i => i.Variations)
                        .ThenInclude(i => i.Qualities)
                    .OrderBy(i => i.IceCreamId)
                    .FirstOrDefault();

                Debug.Assert(iceCreamWithNewVariations.Variations.Count == 2);
            }
        }
    }
}

使用此控制台 .csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.1.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.1" />
  </ItemGroup>

</Project>

使用:

docker-compose down
docker-compose up -d
dotnet run

如果您看到日志:

  • 先去掉质量(没关系)
  • 然后添加新的变体(这是不正确的)
  • 旧的变体被移除(这应该在添加新的变体之前发生)

如果您没有每个变体的嵌套特性,则似乎不会发生这种行为。

【问题讨论】:

    标签: c# mysql entity-framework-core ef-core-3.0 pomelo-entityframeworkcore-mysql


    【解决方案1】:

    有关解决方法,请参阅下面的“解决方法”。


    您使用DbSet.Update 的具体原因是什么?它具有与跟踪有关的非常特殊的目的。

    相反,删除旧项目并添加新项目就足够了:

    model.Items.Remove(someOldItem); // or use other `Remove` methods
    model.Items.AddRange(newItems);
    context.SaveChanges();
    
    

    下面是一个完整的例子:

    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Logging;
    
    namespace IssueConsoleTemplate
    {
        public class IceCream
        {
            public int IceCreamId { get; set; }
            public string Name { get; set; }
    
            public ICollection<IceCreamVariation> Variations { get; set; } = new HashSet<IceCreamVariation>();
        }
    
        public class IceCreamVariation
        {
            public int IceCreamVariationId { get; set; }
            public string Name { get; set; }
            public int IceCreamId { get; set; }
    
            public IceCream IceCream { get; set; }
        }
    
        public class Context : DbContext
        {
            public DbSet<IceCream> IceCreams { get; set; }
            public DbSet<IceCreamVariation> IceCreamVariations { get; set; }
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder
                    .UseMySql(
                        "server=127.0.0.1;port=3306;user=root;password=;database=So61383388",
                        b => b.ServerVersion("8.0.20-mysql"))
                    .UseLoggerFactory(
                        LoggerFactory.Create(
                            b => b
                                .AddConsole()
                                .AddFilter(level => level >= LogLevel.Information)))
                    .EnableSensitiveDataLogging()
                    .EnableDetailedErrors();
            }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<IceCream>()
                    .HasData(
                        new IceCream {IceCreamId = 1, Name = "Vanilla"},
                        new IceCream {IceCreamId = 2, Name = "Chocolate"}
                    );
    
                modelBuilder.Entity<IceCreamVariation>()
                    .HasData(
                        new IceCreamVariation {IceCreamVariationId = 1, Name = "Double Vanilla Bourbon", IceCreamId = 1},
                        new IceCreamVariation {IceCreamVariationId = 2, Name = "Vanilla Caramel", IceCreamId = 1},
                        new IceCreamVariation {IceCreamVariationId = 3, Name = "Chocolate Hazelnut", IceCreamId = 2}
                    );
            }
        }
    
        internal class Program
        {
            private static void Main()
            {
                using (var context = new Context())
                {
                    context.Database.EnsureDeleted();
                    context.Database.EnsureCreated();
    
                    var iceCreamsWithOldVariations = context.IceCreams
                        .Include(i => i.Variations)
                        .OrderBy(i => i.IceCreamId)
                        .ToList();
    
                    Debug.Assert(iceCreamsWithOldVariations.Count == 2);
                    Debug.Assert(iceCreamsWithOldVariations[0].Variations.Count == 2);
                    Debug.Assert(iceCreamsWithOldVariations[1].Variations.Count == 1);
    
                    var vanillaIceCream = iceCreamsWithOldVariations[0];
                    var vanillaCaramelVariation = iceCreamsWithOldVariations[0].Variations.First();
                    vanillaIceCream.Variations.Remove(vanillaCaramelVariation);
                    vanillaIceCream.Variations.Add(new IceCreamVariation {Name = "Vanilla Cheesecake"});
                    vanillaIceCream.Variations.Add(new IceCreamVariation {Name = "Vanilla-Lemon"});
    
                    var cholocateIceCream = iceCreamsWithOldVariations[1];
                    cholocateIceCream.Variations.Clear();
                    cholocateIceCream.Variations.Add(new IceCreamVariation {Name = "Chocolate Fudge Brownie"});
                    cholocateIceCream.Variations.Add(new IceCreamVariation {Name = "Chocolate-Peanut Butter"});
    
                    context.SaveChanges();
    
                    var iceCreamsWithNewVariations = context.IceCreams
                        .Include(i => i.Variations)
                        .OrderBy(i => i.IceCreamId)
                        .ToList();
    
                    Debug.Assert(iceCreamsWithNewVariations.Count == 2);
                    Debug.Assert(iceCreamsWithNewVariations[0].Variations.Count == 3);
                    Debug.Assert(iceCreamsWithNewVariations[1].Variations.Count == 2);
                }
            }
        }
    }
    

    正在生成以下 SQL 语句,它们按预期工作:

    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (6ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          CREATE DATABASE `So61383388`;
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (38ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          CREATE TABLE `IceCreams` (
              `IceCreamId` int NOT NULL AUTO_INCREMENT,
              `Name` longtext CHARACTER SET utf8mb4 NULL,
              CONSTRAINT `PK_IceCreams` PRIMARY KEY (`IceCreamId`)
          );
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (35ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          CREATE TABLE `IceCreamVariations` (
              `IceCreamVariationId` int NOT NULL AUTO_INCREMENT,
              `Name` longtext CHARACTER SET utf8mb4 NULL,
              `IceCreamId` int NOT NULL,
              CONSTRAINT `PK_IceCreamVariations` PRIMARY KEY (`IceCreamVariationId`),
              CONSTRAINT `FK_IceCreamVariations_IceCreams_IceCreamId` FOREIGN KEY (`IceCreamId`) REFERENCES `IceCreams` (`IceCreamId`) ON DELETE CASCADE
          );
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (6ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          INSERT INTO `IceCreams` (`IceCreamId`, `Name`)
          VALUES (1, 'Vanilla');
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          INSERT INTO `IceCreams` (`IceCreamId`, `Name`)
          VALUES (2, 'Chocolate');
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (6ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          INSERT INTO `IceCreamVariations` (`IceCreamVariationId`, `IceCreamId`, `Name`)
          VALUES (1, 1, 'Double Vanilla Bourbon');
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          INSERT INTO `IceCreamVariations` (`IceCreamVariationId`, `IceCreamId`, `Name`)
          VALUES (2, 1, 'Vanilla Caramel');
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          INSERT INTO `IceCreamVariations` (`IceCreamVariationId`, `IceCreamId`, `Name`)
          VALUES (3, 2, 'Chocolate Hazelnut');
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (30ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          CREATE INDEX `IX_IceCreamVariations_IceCreamId` ON `IceCreamVariations` (`IceCreamId`);
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          SELECT `i`.`IceCreamId`, `i`.`Name`, `i0`.`IceCreamVariationId`, `i0`.`IceCreamId`, `i0`.`Name`
          FROM `IceCreams` AS `i`
          LEFT JOIN `IceCreamVariations` AS `i0` ON `i`.`IceCreamId` = `i0`.`IceCreamId`
          ORDER BY `i`.`IceCreamId`, `i0`.`IceCreamVariationId`
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (7ms) [Parameters=[@p0='1', @p1='3', @p2='1', @p3='Vanilla Cheesecake' (Size = 4000), @p4='1', @p5='Vanilla-Lemon' (Size = 4000), @p6='2', @p7='Chocolate Fudge Brownie' (Size = 4000), @p8='2', @p9='Chocolate-Peanut Butter' (Size = 4000)], CommandType='Text', CommandTimeout='30']
    
          DELETE FROM `IceCreamVariations`
          WHERE `IceCreamVariationId` = @p0;
          SELECT ROW_COUNT();
    
          DELETE FROM `IceCreamVariations`
          WHERE `IceCreamVariationId` = @p1;
          SELECT ROW_COUNT();
    
          INSERT INTO `IceCreamVariations` (`IceCreamId`, `Name`)
          VALUES (@p2, @p3);
          SELECT `IceCreamVariationId`
          FROM `IceCreamVariations`
          WHERE ROW_COUNT() = 1 AND `IceCreamVariationId` = LAST_INSERT_ID();
    
          INSERT INTO `IceCreamVariations` (`IceCreamId`, `Name`)
          VALUES (@p4, @p5);
          SELECT `IceCreamVariationId`
          FROM `IceCreamVariations`
          WHERE ROW_COUNT() = 1 AND `IceCreamVariationId` = LAST_INSERT_ID();
    
          INSERT INTO `IceCreamVariations` (`IceCreamId`, `Name`)
          VALUES (@p6, @p7);
          SELECT `IceCreamVariationId`
          FROM `IceCreamVariations`
          WHERE ROW_COUNT() = 1 AND `IceCreamVariationId` = LAST_INSERT_ID();
    
          INSERT INTO `IceCreamVariations` (`IceCreamId`, `Name`)
          VALUES (@p8, @p9);
          SELECT `IceCreamVariationId`
          FROM `IceCreamVariations`
          WHERE ROW_COUNT() = 1 AND `IceCreamVariationId` = LAST_INSERT_ID();
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
    
          SELECT `i`.`IceCreamId`, `i`.`Name`, `i0`.`IceCreamVariationId`, `i0`.`IceCreamId`, `i0`.`Name`
          FROM `IceCreams` AS `i`
          LEFT JOIN `IceCreamVariations` AS `i0` ON `i`.`IceCreamId` = `i0`.`IceCreamId`
          ORDER BY `i`.`IceCreamId`, `i0`.`IceCreamVariationId`
    

    我想知道这种行为是否可以以某种方式配置,以及为什么只有在插入后才删除相关实体,而反之亦然。

    您可以看到,DELETE 语句在INSERT 语句之前执行


    更新

    使用您提供的新示例代码,我能够重现该问题。这似乎是 EF Core(不是 Pomelo)中的一个错误,因为 SQL Server 可以重现相同的行为:

    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Logging;
    
    namespace IssueConsoleTemplate
    {
        public class IceCream
        {
            public int IceCreamId { get; set; }
            public string Name { get; set; }
    
            public ICollection<IceCreamVariation> Variations { get; set; } = new HashSet<IceCreamVariation>();
        }
    
        public class IceCreamVariation
        {
            public int IceCreamVariationId { get; set; }
            public string Name { get; set; }
            public int UniqueId { get; set; }
            public int IceCreamId { get; set; }
    
            public IceCream IceCream { get; set; }
    
            public ICollection<IceCreamVariationQuality> Qualities { get; set; } = new HashSet<IceCreamVariationQuality>();
        }
    
        public class IceCreamVariationQuality
        {
            public int IceCreamVariationQualityId { get; set; }
            public string Name { get; set; }
            public int IceCreamVariationId { get; set; }
    
            public IceCreamVariation IceCreamVariation { get; set; }
        }
    
        public class Context : DbContext
        {
            public DbSet<IceCream> IceCreams { get; set; }
            public DbSet<IceCreamVariation> IceCreamVariations { get; set; }
            public DbSet<IceCreamVariationQuality> IceCreamVariationQualities { get; set; }
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder
                    .UseSqlServer(@"Data Source=.\MSSQL14;Integrated Security=true;Initial Catalog=So61383388_01")
                    //.UseMySql(
                    //    "server=127.0.0.1;port=3308;user=root;password=;database=So61383388_01",
                    //    b => b.ServerVersion("8.0.20-mysql"))
                    .UseLoggerFactory(
                        LoggerFactory.Create(
                            b => b
                                .AddConsole()
                                .AddFilter(level => level >= LogLevel.Information)))
                    .EnableSensitiveDataLogging()
                    .EnableDetailedErrors();
            }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<IceCream>()
                    .HasData(
                        new IceCream {IceCreamId = 1, Name = "Vanilla"}
                    );
    
                modelBuilder.Entity<IceCreamVariation>(
                    entity =>
                    {
                        entity.HasAlternateKey(e => e.UniqueId);
    
                        entity.HasData(
                            new IceCreamVariation
                            {
                                IceCreamVariationId = 1,
                                Name = "Double Vanilla Bourbon",
                                UniqueId = 42, // this value is part of a unique index
                                IceCreamId = 1
                            }
                        );
                    });
    
                modelBuilder.Entity<IceCreamVariationQuality>()
                    .HasData(
                        new IceCreamVariationQuality
                        {
                            IceCreamVariationQualityId = 1,
                            Name = "Yummy",
                            IceCreamVariationId = 1
                        }
                    );
            }
        }
    
        internal class Program
        {
            private static void Main()
            {
                using (var context = new Context())
                {
                    context.Database.EnsureDeleted();
                    context.Database.EnsureCreated();
    
                    var iceCreamWithOldVariations = context.IceCreams
                        .Include(i => i.Variations)
                            .ThenInclude(i => i.Qualities)
                        .OrderBy(i => i.IceCreamId)
                        .First();
    
                    Debug.Assert(iceCreamWithOldVariations.Variations.Count == 1);
                    Debug.Assert(iceCreamWithOldVariations.Variations.Single().UniqueId == 42);
                    Debug.Assert(iceCreamWithOldVariations.Variations.Single().Qualities.First().Name == "Yummy");
    
                    iceCreamWithOldVariations.Variations.Clear();
                    iceCreamWithOldVariations.Variations.Add(
                        new IceCreamVariation 
                        {
                            Name = "Vanilla Cheesecake",
                            UniqueId = 42, // use same value again; should work because previous entity was removed
                            Qualities = new[]
                            {
                                new IceCreamVariationQuality { Name = "Healthy" },
                            },
                        });
    
                    context.SaveChanges();
    
                    var iceCreamWithNewVariations = context.IceCreams
                        .Include(i => i.Variations)
                            .ThenInclude(i => i.Qualities)
                        .OrderBy(i => i.IceCreamId)
                        .First();
    
                    Debug.Assert(iceCreamWithNewVariations.Variations.Count == 1);
                    Debug.Assert(iceCreamWithNewVariations.Variations.Single().UniqueId == 42);
                    Debug.Assert(iceCreamWithNewVariations.Variations.Single().Qualities.First().Name == "Healthy");
                }
            }
        }
    }
    

    如果在声明UniqueId属性时执行,则会抛出异常,生成的SQL更加意外:

    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (15ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
          SET NOCOUNT ON;
          DELETE FROM [IceCreamVariationQualities]
          WHERE [IceCreamVariationQualityId] = @p0;
          SELECT @@ROWCOUNT;
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (3ms) [Parameters=[@p1='1', @p0='Vanilla Cheesecake' (Size = 4000)], CommandType='Text', CommandTimeout='30']
          SET NOCOUNT ON;
          UPDATE [IceCreamVariations] SET [Name] = @p0
          WHERE [IceCreamVariationId] = @p1;
          SELECT [IceCreamVariationId]
          FROM [IceCreamVariations]
          WHERE @@ROWCOUNT = 1 AND [IceCreamVariationId] = scope_identity();
    

    这里,已经生成了一个UPDATE 语句来更改IceCreamVariations 实体的名称(这是错误的),假设该实体刚刚被插入(事实并非如此),因为它使用@987654335 @。


    解决方法:

    讨论继续在GitHub

    在那里,@smitpatel 建议尝试使用entity.HasIndex(e =&gt; e.UniqueId).IsUnique() 而不是entity.HasAlternateKey(e =&gt; e.UniqueId),它按预期工作。

    因此,在模型定义中定义唯一索引而不是备用键是解决此问题的有效解决方法:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // ...
    
        modelBuilder.Entity<IceCreamVariation>(
            entity =>
            {
                // This does not work:
                // entity.HasAlternateKey(e => e.UniqueId);
    
                // This *does* work:
                entity.HasIndex(e => e.UniqueId)
                    .IsUnique();
    
                entity.HasData(
                    new IceCreamVariation
                    {
                        IceCreamVariationId = 1,
                        Name = "Double Vanilla Bourbon",
                        UniqueId = 42, // this value is part of a unique index
                        IceCreamId = 1
                    }
                );
            });
    
        // ...
    }
    

    【讨论】:

    • 我不确定我是否遵循。 DbSet.Update 是否会导致这些问题?
    • 即使删除DbSet.Update 调用并使用model.Items.Clear(),错误仍然存​​在。
    • @ShoeDiamente 我添加了一个完整的示例控制台项目,因此您可以看看它是如何工作的,也可以在您的最终测试它。
    • 非常感谢。我通过将另一个子模型添加到 IceCreamVariation 对您的 C# 程序进行了一些修改,以便它等同于我的用例:pastebin.com/pnJniaMy。如您所见,输出显示首先删除了IceCreamVariationQualitys,然后在删除旧的之前插入了IceCreamVariations。这是我的示例日志:pastebin.com/0W3JXhgw.
    • 没问题。我们在讨论期间发现了备用关键错误,因此由于这个问题,EF Core 将针对 .NET 5 的这种情况进行改进。
    猜你喜欢
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多