整个框架核心复杂类型作为主键

问题描述 投票:0回答:1

官方文档有如下描述

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 表的示例。

enter image description here

c# .net entity-framework-core
1个回答
0
投票

如果有人对此仍然感兴趣。在 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");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.