将项目从 dotnet core 2.0 迁移到 3.1 并在 Entity Framework 上遇到一些问题

Migrating project from dotnet core 2.0 to 3.1 and having some problems on Entity Framework

我正在使用 DDD 构建一个项目。因此 update/add/delete 子实体的唯一方法是通过其父实体,当我使用 dotnet core 2.0 时这不是问题但现在我正在将项目迁移到 dotnet core 3.1 我收到以下错误:

Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.

我有一个这样的客户class:

public class Client
{
    /// <summary>
    /// DDD Patterns comment Using a private collection field, better for DDD Aggregate's
    /// encapsulation so Receptions cannot be added from "outside the AggregateRoot" directly to
    /// the collection, but only through the method ClientAggrergateRoot.AddReception() which
    /// includes behaviour.
    /// </summary>
    private readonly List<Reception> _receptions;

    public Client(Guid id, string name, string url, string domainEmail)
    {
        Id = id;
        Name = name;
        Url = url;
        DomainEmail = domainEmail;
        _receptions = new List<Reception>();
    }

    protected Client()
    {
        _receptions = new List<Reception>();
    }

    public string Name { get; private set; }

    public string Url { get; private set; }

    public string DomainEmail { get; private set; }

    public bool IsDeleted { get; private set; }

    public DateTime CreatedAt { get; private set; }

    public DateTime ModifiedAt { get; private set; }

    public IReadOnlyCollection<Reception> Receptions => _receptions;        
}

我有我的招待会class:

public class Reception
{
    public Reception(Guid id, string name, string address, string noteToGuest, string noteToReceptionst,
        string timeZone, Guid clientId)
    {
        Id = id;
        Name = name;
        Address = address;
        ClientId = clientId;
    }

    private Reception()
    {
    }

    public Guid ClientId { get; private set; }

    public string Name { get; private set; }

    public string Address { get; private set; }        
}

这是客户端配置文件:

public class ClientEntityTypeConfiguration
    : IEntityTypeConfiguration<Client>
{
    public void Configure(EntityTypeBuilder<Client> builder)
    {
        builder.ToTable("Clients", BeWelcomeContext.CLIENT_SCHEMA);
        builder.HasKey(c => c.Id);            

        var navigation = builder.Metadata.FindNavigation(nameof(Client.Receptions));

        // DDD Patterns comment: Set as field (New since EF 1.1) to acces the Receptions
        // collection property through its fields
        navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
    }
}

以及接收配置文件:

public class ReceptionEntityTypeConfiguration
    : IEntityTypeConfiguration<Reception>
{
    public void Configure(EntityTypeBuilder<Reception> builder)
    {
        builder.ToTable("Receptions", BeWelcomeContext.CLIENT_SCHEMA);
        builder.HasKey(r => r.Id);

        builder.HasOne<Client>()
            .WithMany(r => r.Receptions)
            .IsRequired()
            .HasForeignKey(r => r.ClientId);
    }
}

在我进行项目迁移之前,它一直运行良好,如果我必须更改一些配置,我不知道发生了什么。

Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.

您的数据库似乎阻止修改数据。查看您的日志,复制由 EF Core 创建的 SQL 查询并尝试在您的 DBMS 中 运行 它,也许您会得到更详细的错误。通常有一个触发器阻止执行操作。

https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#detectchanges-honors-store-generated-key-values

这是 dot net 3.0 中的重大更改。

如果您使用 Guid 键并预生成它们(我正在做同样的 DDD 事情),那么 Ef 现在将其视为修改后的对象而不是新对象。

解决方案是关闭模型的密钥生成。

上面link有详细的解释。 但总而言之,您需要在 DbContext OnModelCreating

中进行此更改
modelBuilder
.Entity<Client>()
.Property(e => e.Id)
.ValueGeneratedNever();

如果模型派生自某些 class,例如具有 ID 属性 的实体,那么可能会使用更好的解决方法,

 [DatabaseGenerated(DatabaseGeneratedOption.None)]
 public string Id { get; set; }

在父项上设置此项将在 class 之后应用它。