如何让EFCore In-memory db自动增加非关键字段
How to get EFCore In-memory db to auto-increment non-key fields
我们有一个在 guid 上键入的实体,该实体使用另一个基于自动递增 int 属性 的人类可读密钥。这在 运行 应用程序时按预期工作。
出于测试目的,我们使用的是 EF 内存数据库,但这似乎只会自动增加一个列,如果它也是一个键。
使用 属性 注释属性或流畅的 API 都没有效果。
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int OrderNumber { get; private set; }
===========
modelBuilder.Entity<Order>(order =>
{
order.Property(p => p.OrderNumber).ValueGeneratedOnAdd();
});
在这两种情况下,OrderNumber 在插入后都保留为 0。有没有办法让内存数据库执行此操作,或者这是一个已知的限制? (谷歌搜索发现了关于键值重新播种的问题,但不是这个特定问题)
非键属性的值生成工作方式不同(不知道为什么)- 当 属性 没有分配明确的值生成器时不会触发。对于生成临时密钥的提供程序,它可以工作,因为实际值是在 SaveChanges
之后分配的。但是 in-memory provider value generators 生成持久键,并且由于它们不是为非键属性调用的,所以 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()
。
我们有一个在 guid 上键入的实体,该实体使用另一个基于自动递增 int 属性 的人类可读密钥。这在 运行 应用程序时按预期工作。
出于测试目的,我们使用的是 EF 内存数据库,但这似乎只会自动增加一个列,如果它也是一个键。
使用 属性 注释属性或流畅的 API 都没有效果。
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int OrderNumber { get; private set; }
===========
modelBuilder.Entity<Order>(order =>
{
order.Property(p => p.OrderNumber).ValueGeneratedOnAdd();
});
在这两种情况下,OrderNumber 在插入后都保留为 0。有没有办法让内存数据库执行此操作,或者这是一个已知的限制? (谷歌搜索发现了关于键值重新播种的问题,但不是这个特定问题)
非键属性的值生成工作方式不同(不知道为什么)- 当 属性 没有分配明确的值生成器时不会触发。对于生成临时密钥的提供程序,它可以工作,因为实际值是在 SaveChanges
之后分配的。但是 in-memory provider value generators 生成持久键,并且由于它们不是为非键属性调用的,所以 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()
。