实体框架核心-复杂类型在postgres中映射为jsonb列,但InMemory提供程序的映射失败



有一种类型的复杂属性如下:

[Table("contact")]
public class Contact
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("details", TypeName = "jsonb")]
public Details Details { get; set; }
... 
}
[ComplexType]
public class Details
{
[JsonProperty("firstName")]
public string FirstName { get; set; }
[JsonProperty("middleName")]
public string MiddleName { get; set; }
[JsonProperty("lastName")]
public string LastName { get; set; }
}

适用于pgsql提供程序:

services.AddDbContextPool<ProfileDbContext>((sp, options) =>
{
options.UseNpgsql(connStr,
x =>
{
x.EnableRetryOnFailure();
x.CommandTimeout(120);
});
});

但是当在TestsStartup中将其替换为InMemory提供商时

services.AddDbContextPool<ProfileDbContext>(options =>
{
ServiceProvider sp = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
options.UseInMemoryDatabase("Profile", _databaseRoot);
options.UseInternalServiceProvider(sp);
});

出现错误:

实体类型"Details"需要定义主键。如果你旨在使用无键实体类型调用"HasNoKey(("。

如果我通过fluent配置指定关联OwnsOne,它适用于InMemory,但在使用pgsql提供程序启动正常启动时失败

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Contact>(c => c.OwnsOne(e => e.Details));
}

我想是因为这个jsonb文件类型,InMemory提供程序不支持它,是吗?

如何处理集成测试?

我们在所有测试中都使用了内存内提供程序,但这个jsonb功能似乎破坏了内存内提供方的生命。

InMemory是一个非常有限的测试解决方案,因为它实际上不能做许多真实数据库可以做的事情——事务、原始SQL,在这种情况下还有jsonb类型。

对于完全集成测试,一般建议使用实际的生产数据库,为您提供最佳的测试保真度-EF Core文档提供了这方面的详细信息。否则,对于单元测试,您可以有一个存储库抽象并模拟它,在这种情况下,您根本不需要使用EFCore。

在您的dbcontext moc:中

public class PostgreSqlDbContextMock : PostgreDbContext
{
public PostgreSqlDbContextMock(DbContextOptions<PostgreSqlDbContextMock> options) : base(options)
{
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseInMemoryDatabase(Guid.NewGuid().ToString());
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<EntityWithJsonbProperty>().Property(x => x.SessionData).HasConversion(
v => JsonConvert.SerializeObject(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
v => JsonConvert.DeserializeObject<YouJsonbProperty>(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));
}
}

最新更新