官方文档有如下描述
EF Core 支持使用任何基元类型的属性作为主键
https://learn.microsoft.com/en-us/ef/core/modeling/keys?tabs=data-annotations#key-types-and-values
这说明不能使用Complex类型作为主键。 这种理解正确吗?
事实上,下面的代码都会出错。
entity.HasKey(e => new {e.SalesOrderKey.SalesOrderId, e.SalesOrderKey.SalesOrderDetailId});
entity.HasKey(e => e.SalesOrderKey);
这是 Adventure Works(一个示例 SQL Server 数据库)中 SalesOrderDetail 表的示例。
如果有人对此仍然感兴趣。在 EF Core 8 中可以使用复杂类型作为主键。
实体配置:
internal class ProductEntityTypeConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.ComplexProperty(p => p.Id, b =>
{
b.Property(pid => pid.Name)
.HasColumnName("Name");
b.Property(pid => pid.CategoryId)
.HasColumnName("CategoryId");
});
builder.Property("_categoryId").HasColumnName("CategoryId");
builder.Property("_name")
.HasMaxLength(50)
.HasColumnName("Name")
.IsUnicode(false);
builder.HasKey(["_categoryId", "_name"]);
}
}
使用复杂类型作为主键(int和string)的模型:
public readonly record struct ProductId(int CategoryId, string Name);
public class Product
{
private readonly int _categoryId;
private readonly string _name;
private Product() { }
public Product(ProductId id)
{
Id = id;
_categoryId = id.CategoryId;
_name = id.Name;
}
public ProductId Id { get; private set; }
}
内部场在这里至关重要。它们用于声明主键,EF 需要它们来跟踪实体。但对于外界来说,Id 是基于记录结构的复杂类型 ProductId。 生成的迁移:
public partial class ComplexProperty : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Product",
columns: table => new
{
CategoryId = table.Column<int>(type: "int", nullable: false),
Name = table.Column<string>(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Product", x => new { x.CategoryId, x.Name });
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Product");
}
}