背景
我的应用程序使用具有驼峰式命名约定的 PostgreSQL 数据库。
使用 EF Core 8.0.1,我尝试在 C# (PascalCase) 中使用具有不同命名约定的 Jsonb 列
每个其他表名称、属性、主键和外键都在特定的
OnModelCreating
函数上更新,该函数将每个值转换为驼峰命名法。
示例
我有一个
OrderEntity
,目前由多个属性组成:
[Index(nameof(Reference), IsUnique = true)]
public class OrderEntity : BaseEntity
{
public Guid Id { get; set; }
public required string Reference { get; set; }
public Guid OrganizationId { get; set; }
//Other properties here...
public required OrderAddress ShippingAddress { get; set; }
public OrganizationEntity Organization { get; set; } = null!;
}
ShippingAddress
是PostgreSQL中的一个jsonb列,里面有以下属性:
public class OrderAddress
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Street { get; set; }
public string? ZipCode { get; set; }
public string? City { get; set; }
public OrderAddressCountry? Country { get; set; }
public OrderAddressCompany? Company { get; set; }
}
ShippingAddress
的配置是在我的dbContext
文件中使用FluentAPI进行的:
public class OrderManagementDbContext(DbContextOptions<OrderManagementDbContext> options) : DbContext(options)
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<orderEntity>().OwnsOne(
order => order.ShippingAddress, ownedNavigationBuilder =>
{
ownedNavigationBuilder.ToJson();
ownedNavigationBuilder.OwnsOne(shippingAddress => shippingAddress.Country);
ownedNavigationBuilder.OwnsOne(shippingAddress => shippingAddress.Company);
});
modelBuilder.ConfigureCamelCase();
}
//Tables
public virtual DbSet<OrderEntity> Orders { get; set; }
}
结果
针对
orderEntity
执行请求时,出现以下错误:
Npgsql.PostgresException(0x80004005):42703:列 p.ShippingAddress 不存在
当我创建迁移时,我的表反映了此命名约定问题:
migrationBuilder.CreateTable(
name: "order",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
reference = table.Column<string>(type: "text", nullable: false),
organizationId = table.Column<Guid>(type: "uuid", nullable: false),
ShippingAddress = table.Column<string>(type: "jsonb", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("order_pkey", x => x.id);
table.ForeignKey(
name: "order_organization_organizationId_fkey",
column: x => x.organizationId,
principalTable: "organization",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
我已经尝试过这些方法但没有成功:
全局更新
JsonSerializerOptions.PropertyNamingPolicy
为 JsonNamingPolicy.CamelCase
全局设置
JsonSerializerOptions.PropertyNameCaseInsensitive
为 false
设置
ShippingAddress
带有列数据注释的名称
使用 Fluent API
ShippingAddress
函数设置 HasColumnName
名称
使用
ShippingAddress
和 OwnsOne
函数在 ToTable
函数中设置 ExcludeFromMigrations
名称
使用
modelBuilder.Model.GetEntityTypes().GetDeclaredNavigations()
以驼峰式大小写手动设置导航名称,然后检查 IsOwned()
targetEntityType,然后使用 SetField
函数:
foreach (var navigationProperty in tableConfiguration.GetDeclaredNavigations())
{
if (navigationProperty.TargetEntityType.IsOwned())
{
navigationProperty.SetField(navigationProperty.Name.ToCamelCase());
}
}
但是我在运行突变时遇到另一个错误:
无法创建类型为“”的“DbContext”。异常“无法为属性“OrderEntity.ShippingAddress”找到指定字段“shippingAddress”。”尝试创建实例时抛出。有关设计时支持的不同模式,请参阅 https://go.microsoft.com/fwlink/?linkid=851728
与 6 相同的测试,使用“GetNavigations()”而不是“GetDeclaredNavigations”
感谢您的帮助!
通过以下选择解决:
builder.Services.AddDbContext<OrderManagementDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("LocalConnectionString"))
.UseCamelCaseNamingConvention());