You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中ValueObject报错:实体类型SkillLevel需定义主键

EF Core值对象主键错误解决

我的代码

SkillLevel值对象类

using System.Runtime.CompilerServices;
using System.Collections.Generic;

namespace sales.Domain.Common.ValueObjects
{
    public record SkillLevel 
    {
        List<Skill> Skill; 
        List<Level> Level; 

        private SkillLevel() { }

        public SkillLevel(List<Skill> skill, List<Level> level) 
        {
            Skill = skill;
            Level = level;
        }
    }
}

EmployeeSkillType配置类

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

using Pluralize.NET;
using sales.Domain.Common.BaseEntities;
using sales.Domain.Entities.Payroll;

namespace sales.Infrastructure.Data.Configs.Payroll
{
    internal class EmployeeSkillTypeConfiguration : IEntityTypeConfiguration<EmployeeSkillType>
    {
        public void Configure(EntityTypeBuilder<EmployeeSkillType> builder)
        {
            builder.ToTable(new Pluralizer().Pluralize(nameof(EmployeeSkillType)));
            builder.HasKey(ii => new { ii.EmployeeGuid, ii.SkillTypeGuid });
            builder.HasOne(e => e.Employee)
                .WithMany(es => es.EmployeeSkillType);
            builder.HasOne(st => st.SkillType)
                .WithMany(es => es.EmployeeSkillType);
            builder.HasMany(sl => sl.SKillLevels).WithOne();

            builder.Navigation(e => e.Employee).AutoInclude();
            builder.Navigation(st => st.SkillType).AutoInclude();
        }
    }
}

遇到的错误

实体类型'SkillLevel'需要定义主键。如果您打算使用无键实体类型,请在'OnModelCreating'中调用'HasNoKey'。有关无键实体类型的更多信息...

已尝试操作

  • 尝试将SkillLevels改为jsonb类型存储,但出现其他错误。

解决方案

SkillLevel是值对象,不是独立实体,EF Core默认会把它当成实体处理,要明确告诉EF Core它的角色,以下两种方案任选:

方案1:配置为拥有类型(Owned Type)

把原来的HasMany配置替换成拥有类型的配置,EF会把值对象作为从属数据存储,无需主键:

// 替换builder.HasMany(sl => sl.SKillLevels).WithOne();这一行
builder.OwnsMany(sl => sl.SKillLevels, ownedBuilder =>
{
    // 如果Skill和Level也是值对象,继续配置它们的拥有关系
    ownedBuilder.OwnsMany(s => s.Skill);
    ownedBuilder.OwnsMany(l => l.Level);
    // 若需要自定义列名或约束,可在此添加配置
});

方案2:正确配置JSONB列存储

之前转jsonb出错大概率是没正确配置序列化/反序列化,按下面步骤来:

  1. 确保数据库支持JSONB(比如PostgreSQL)
  2. 修改配置类中的属性映射:
// 替换原来的HasMany配置
builder.Property(e => e.SKillLevels)
    .HasColumnType("jsonb")
    .HasConversion(
        levels => System.Text.Json.JsonSerializer.Serialize(levels, null),
        json => System.Text.Json.JsonSerializer.Deserialize<List<SkillLevel>>(json, null)
    );

同时注意:

  • SkillLevel、Skill、Level需要有无参构造函数(或者在JsonSerializer中配置允许使用私有构造函数)
  • 把类中的私有属性改为public,或者配置JsonSerializer能访问私有成员
  • 检查SKillLevels的拼写(S大写、kill小写,可能是笔误)

内容的提问来源于stack exchange,提问作者alyawdi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 01:53:19