如何获取 EFCore 内存中数据库以自动递增非键字段



我们有一个实体,它基于自动递增的int属性,使用另一个人类可读的键。运行应用时,这将按预期工作。

出于测试目的,我们使用 EF 内存中数据库,但这似乎只会在列也是键的情况下自动递增列。

使用属性注释属性或流畅 API 不起作用。

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int OrderNumber { get; private set; }
    ===========
    modelBuilder.Entity<Order>(order =>
    {
        order.Property(p => p.OrderNumber).ValueGeneratedOnAdd();
    });

在这两种情况下,插入后订单号都保留为 0。 有没有办法让内存中的数据库执行此操作,或者这是一个已知的限制? (谷歌搜索发现了有关重新播种键值的问题,但不是这个特定问题(

非键属性的值生成的工作方式不同(不知道为什么( - 当属性没有分配显式值生成器时,不会触发它。对于生成临时密钥的提供程序,它之所以有效,是因为实际值是在 SaveChanges 之后分配的。但是内存中提供程序值生成器会生成持久键,并且由于它们不是为非键属性调用的,因此ValueGeneratedOnAdd不起作用。

解决方法是为此类属性显式分配值生成器。您需要以下命名空间:

using Microsoft.EntityFrameworkCore.InMemory.ValueGeneration.Internal;

然后是类似于下面的代码:

modelBuilder.Entity<Order>(order =>
{
    var orderNumber = order.Property(p => p.OrderNumber);
    orderNumber.ValueGeneratedOnAdd();
    // only for in-memory
    if (Database.IsInMemory())
        orderNumber.HasValueGenerator<InMemoryIntegerValueGenerator<int>>();
});

你也可以编写自己的ValueGenerator。

public class OrderIdValueGenerator : ValueGenerator<int>
{
    private int _current;
    public override bool GeneratesTemporaryValues => false;
    public override int Next(EntityEntry entry)
        => Interlocked.Increment(ref _current);
}

然后像这样使用它:

modelBuilder.Entity<Order>(order =>
{
    order.Property(p => p.OrderNumber).HasValueGenerator<OrderIdValueGenerator>();
});

您不必指定.ValueGeneratedOnAdd()

相关内容

  • 没有找到相关文章

最新更新