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

.NET迁移报错:实体类型List<int>需定义主键,求解决方案

问题描述

我在使用.NET进行数据迁移时遇到问题。

定义的抽象类:

[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("UserId")]
public int UserId { get; set; }
public DateTime? DateTime { get; set; }
public virtual User User { get; set; }

随后创建了两个派生实体类:

public class MovieFavoriteList:FavoriteListBase<int>
{
    public List<int> MovieIds { get; set; }
}

public class TvSeriesFavoriteList:FavoriteListBase<int>
{
    public List<int> TvIds { get; set; }
}

执行迁移时出现错误:

The entity type 'List' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'.

我曾尝试给TvSeriesFavoriteList添加[Keyless]特性,但这种做法并不合理,想请教如何解决该问题?

解决方案

EF Core无法直接将List<int>这类集合类型映射为数据库表的字段,它会把集合当成独立实体类型,因此提示需要主键。提供两种可行解决方式:

方法一:用值转换器将集合序列化为字符串

通过EF Core的值转换器,把List<int>序列化为JSON字符串存在数据库单个字段中,读取时再反序列化为集合。

在DbContext的OnModelCreating方法中配置:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 配置MovieFavoriteList的MovieIds字段
    modelBuilder.Entity<MovieFavoriteList>()
        .Property(x => x.MovieIds)
        .HasConversion(
            v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
            v => JsonSerializer.Deserialize<List<int>>(v, (JsonSerializerOptions)null)
        );

    // 配置TvSeriesFavoriteList的TvIds字段
    modelBuilder.Entity<TvSeriesFavoriteList>()
        .Property(x => x.TvIds)
        .HasConversion(
            v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
            v => JsonSerializer.Deserialize<List<int>>(v, (JsonSerializerOptions)null)
        );
}

这种方式适合无需对集合单个元素做查询的简单场景。

方法二:创建关联实体实现多对多关系

如果需要对收藏的电影/电视剧ID做单独查询(比如统计某部电影的收藏量),推荐用标准多对多关系设计:

  1. 创建中间实体:
// 电影收藏中间表实体
public class MovieFavorite
{
    [Key]
    public int Id { get; set; }
    public int MovieFavoriteListId { get; set; }
    public int MovieId { get; set; }

    public virtual MovieFavoriteList MovieFavoriteList { get; set; }
}

// 电视剧收藏中间表实体
public class TvSeriesFavorite
{
    [Key]
    public int Id { get; set; }
    public int TvSeriesFavoriteListId { get; set; }
    public int TvId { get; set; }

    public virtual TvSeriesFavoriteList TvSeriesFavoriteList { get; set; }
}
  1. 修改派生实体类,替换集合类型:
public class MovieFavoriteList:FavoriteListBase<int>
{
    public virtual List<MovieFavorite> MovieFavorites { get; set; } = new List<MovieFavorite>();
}

public class TvSeriesFavoriteList:FavoriteListBase<int>
{
    public virtual List<TvSeriesFavorite> TvSeriesFavorites { get; set; } = new List<TvSeriesFavorite>();
}
  1. 在OnModelCreating中配置关系:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MovieFavorite>()
        .HasOne(f => f.MovieFavoriteList)
        .WithMany(l => l.MovieFavorites)
        .HasForeignKey(f => f.MovieFavoriteListId);

    modelBuilder.Entity<TvSeriesFavorite>()
        .HasOne(f => f.TvSeriesFavoriteList)
        .WithMany(l => l.TvSeriesFavorites)
        .HasForeignKey(f => f.TvSeriesFavoriteListId);
}

这种方式符合关系型数据库设计规范,支持更灵活的数据查询操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:05:49