Entity framework core 如何控制实体框架核心中内存中生成的键值? 背景
我正在开发一个基于ASP.NET Core 2.1和EntityFrameworkCore 2.1.1的Web应用程序。除了其他类型的测试外,我还经常对Web.Api进行一些集成测试 由于测试数据相当复杂,我基于迁移数据库的一个片段生成了一个JSON文件,当内存测试开始时,测试将从这个JSON文件导入数据 问题 只读测试工作正常。但是,当我为具有标识(Entity framework core 如何控制实体框架核心中内存中生成的键值? 背景,entity-framework-core,integration-testing,in-memory-database,Entity Framework Core,Integration Testing,In Memory Database,我正在开发一个基于ASP.NET Core 2.1和EntityFrameworkCore 2.1.1的Web应用程序。除了其他类型的测试外,我还经常对Web.Api进行一些集成测试 由于测试数据相当复杂,我基于迁移数据库的一个片段生成了一个JSON文件,当内存测试开始时,测试将从这个JSON文件导入数据 问题 只读测试工作正常。但是,当我为具有标识(ValueGenerated==ValueGenerated.OnAdd)的实体插入某些内容时,它会自动获得值1(所有PK都是ints)。这是有意
ValueGenerated==ValueGenerated.OnAdd
)的实体插入某些内容时,它会自动获得值1(所有PK都是int
s)。这是有意义的,因为没有指示生成器EF在幕后使用以生成这些值的任何对象根据特定值生成
但是,对于生成现有键值的插入,这显然不能正常工作。
我尝试过的事情
services.AddSingleton();
services.AddSingleton();
Ids生成功能
public const int StartValue=100000000;
类ResettableValueGenerator:ValueGenerator
{
私有内部电流;
public override bool GeneratesTemporaryValues=>false;
公共覆盖int Next(EntityEntry)
{
返回联锁增量(参考电流);
}
public void Reset()=>_current=StartValue;
}
公共静态void ResetValueGenerators(CustomApiContext上下文,IValueGeneratorCache缓存,int startValue=startValue)
{
var allKeyProps=context.Model.GetEntityTypes()
.Select(e=>e.FindPrimaryKey().Properties[0])
其中(p=>p.ClrType==typeof(int));
var keyProps=allKeyProps.Where(p=>p.ValueGenerated==ValueGenerated.OnAdd);
foreach(keyProps中的var keyProperty)
{
变量生成器=(ResettableValueGenerator)cache.GetOrAdd(
keyProperty,
keyProperty.DeclaringEntityType,
(p,e)=>新的ResettableValueGenerator());
generator.Reset();
}
}
调试时,我可以看到我的实体正在迭代,因此应用了重置
将数据推入内存中的数据库
private void InitializeSeeding(IServiceScope范围)
{
使用(范围)
{
var services=scope.ServiceProvider;
尝试
{
var context=services.GetRequiredService();
//这会将反序列化数据+静态数据推送到数据库中
InitDbContext(context);
var valueGeneratorService=services.GetRequiredService();
重置ValueGenerators(上下文、valueGeneratorService);
}
捕获(例外情况除外)
{
var logger=services.GetService();
logger.LogError(例如,“对数据库进行种子设定时发生错误”);
}
}
}
实际插入
这是使用通用存储库完成的,但归结起来是:
Context.Set<T>().Add(entity);
Context.SaveChanges();
Context.Set().Add(实体);
SaveChanges();
问题:如何控制实体框架核心中内存中生成的键值?因此,JSON中的实体插入了它们拥有的任何ID。不起作用的是,当您插入新数据时,它们不会以新值(100000000)开始?@jpgrassi-是的,JSON实际上是具有“小”键的生产类数据的序列化(
public const int StartValue = 100000000;
class ResettableValueGenerator : ValueGenerator<int>
{
private int _current;
public override bool GeneratesTemporaryValues => false;
public override int Next(EntityEntry entry)
{
return Interlocked.Increment(ref _current);
}
public void Reset() => _current = StartValue;
}
public static void ResetValueGenerators(CustomApiContext context, IValueGeneratorCache cache, int startValue = StartValue)
{
var allKeyProps = context.Model.GetEntityTypes()
.Select(e => e.FindPrimaryKey().Properties[0])
.Where(p => p.ClrType == typeof(int));
var keyProps = allKeyProps.Where(p => p.ValueGenerated == ValueGenerated.OnAdd);
foreach (var keyProperty in keyProps)
{
var generator = (ResettableValueGenerator)cache.GetOrAdd(
keyProperty,
keyProperty.DeclaringEntityType,
(p, e) => new ResettableValueGenerator());
generator.Reset();
}
}
private void InitializeSeeding(IServiceScope scope)
{
using (scope)
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<CustomApiContext>();
// this pushes deserialized data + static data into the database
InitDbContext(context);
var valueGeneratorService = services.GetRequiredService<IValueGeneratorCache>();
ResetValueGenerators(context, valueGeneratorService);
}
catch (Exception ex)
{
var logger = services.GetService<ILogger<Startup>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
}
Context.Set<T>().Add(entity);
Context.SaveChanges();