c# - 如何防止 EF Core 将 DDD ValueObjects 创建为表
问题描述
我正在使用 EF Core 5.0.1
我创建了以下 ValueObject
public class Address : BaseValueObject
{
public Address(string street, string zipCode, string city, string state, string country)
{
Street = street;
ZipCode = zipCode;
City = city;
State = state;
Country = country;
}
public string Street { get; set; }
public string ZipCode { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return ZipCode;
yield return City;
yield return State;
yield return Country;
}
}
以及拥有值对象的实体
public class Location : BaseEntity
{
[Required]
public string Name { get; set; }
public Address Address { get; set; }
}
Location对象配置如下
public class LocationConfiguration : BaseEntityConfiguration<Location>
{
public override void Configure(EntityTypeBuilder<Location> builder)
{
builder.OwnsOne(o => o.Address, a =>
{
a.Property(p => p.Street).HasMaxLength(600)
.HasDefaultValue("");
a.Property(p => p.City).HasMaxLength(150)
.HasDefaultValue("");
a.Property(p => p.State).HasMaxLength(60)
.HasDefaultValue("");
a.Property(p => p.ZipCode).HasMaxLength(12)
.HasDefaultValue("");
});
base.Configure(builder);
}
}
问题是 EF Core Migration 仍在将 ValueObjects 创建为数据库中的表。我究竟做错了什么?在生成的迁移代码中,我可以看到以下内容:
migrationBuilder.CreateTable(
name: "Location",
columns: table => new
{
Id = table.Column<long>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", maxLength: 80, nullable: false),
Timestamp = table.Column<string>(type: "TEXT", rowVersion: true, nullable: false, defaultValueSql: "CURRENT_TIMESTAMP")
},
constraints: table =>
{
table.PrimaryKey("PK_Location", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Address",
columns: table => new
{
LocationId = table.Column<long>(type: "INTEGER", nullable: false),
Street = table.Column<string>(type: "TEXT", maxLength: 600, nullable: true, defaultValue: ""),
ZipCode = table.Column<string>(type: "TEXT", maxLength: 12, nullable: true, defaultValue: ""),
City = table.Column<string>(type: "TEXT", maxLength: 150, nullable: true, defaultValue: ""),
State = table.Column<string>(type: "TEXT", maxLength: 60, nullable: true, defaultValue: ""),
Country = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Address", x => x.LocationId);
table.ForeignKey(
name: "FK_Address_Location_LocationId",
column: x => x.LocationId,
principalTable: "Location",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
最后是 DBContext 类
public class MyDbContext : DbContext
{
public PlannerDbContext(DbContextOptions<PlannerDbContext> options)
: base(options)
{
}
public DbSet<Location> Locations { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// do not use plural form for table names
modelBuilder.Model.GetEntityTypes()
.Configure(e => e.SetTableName(e.DisplayName()));
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
}
解决方案
EF 为值对象创建表的原因是更改了表命名约定的代码部分。我想,我已经从一些关于以单数形式设置表名的热问题中复制了它。
此方法modelBuilder.Model.GetEntityTypes()
为模型中的所有对象(包括值对象)返回一个枚举器。针对值对象配置表名属性将导致 EF 将此类型视为实体。
这部分
// do not use plural form for table names
modelBuilder.Model.GetEntityTypes()
.Configure(e => e.SetTableName(e.DisplayName()));
应该改为
// do not use plural form for table names
modelBuilder.Model.GetEntityTypes()
.Where(x => !x.ClrType.IsSubclassOf(typeof(BaseValueObject)))
.Configure(e => e.SetTableName(e.DisplayName()));
推荐阅读
- excel - 如何使用拆分值识别编译错误
- arrays - 遍历 JSON 数组并打印出相同的键值
- ios - 如何让 UITableView 定位在安全区域内
- ms-access - MS Access,在触发器中,SetField to format(Now(),"Short Date") 损坏
- machine-learning - 我应该在哪里通过编码器-解码器架构中的预训练词嵌入?
- sql-server - 使用“in”子句加速 SQL 查询
- css - show div *ngIf 路由器活动导航栏
- javascript - JavaScript switch 语句只返回第一种情况
- unique - 如何防止在 MemSQL 中重复插入行?
- javascript - 如何在 Javascript 中使用 iOS playinline