EF 5 Code First模式下如何存储枚举类型的List集合
现有代码问题排查
你当前直接声明List<Genres>类型属性的写法无法生效,因为EF Core默认没有集合类型到关系型数据库单字段的映射规则,不管是普通枚举还是SmartEnum都无法直接适配这种写法。
以下提供两种不需要额外新增实体的枚举方案,可直接实现需求:
方案1:Flags特性枚举(优先推荐)
适合流派总数不超过64个的场景,性能最优,查询最方便
- 把流派定义为带
[Flags]特性的枚举,所有值按2的幂次赋值:
[Flags] public enum Genres { None = 0, Drama = 1 << 0, // 等价于1 Crime = 1 << 1, // 等价于2 Action = 1 << 2, // 等价于4 Comedy = 1 << 3, // 等价于8 // 后续新增流派依次按位左移赋值即可 }
- 修改
Serie类的属性定义:
class Serie { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } [Required] [MaxLength(255)] public string Titel { get; set; } = ""; // 直接存储组合后的枚举值,EF Core默认映射为int/long字段 public Genres Genres { get; set; } = Genres.None; // 可选:如果需要操作单个流派列表,加非映射属性 [NotMapped] public List<Genres> GenreList { get { return Enum.GetValues<Genres>() .Where(g => g != Genres.None && Genres.HasFlag(g)) .ToList(); } set { Genres = Genres.None; foreach (var genre in value) { Genres |= genre; } } } }
日常操作示例:
- 新增多个流派:
serie.Genres |= Genres.Drama | Genres.Crime - 移除指定流派:
serie.Genres &= ~Genres.Crime - 查询包含指定流派的内容:
db.Series.Where(s => s.Genres.HasFlag(Genres.Drama))
方案2:SmartEnum搭配值转换器
适合流派总数超过64个,无法用Flags枚举覆盖的场景
- 保持你现有的
GenresSmartEnum定义不变,修改Serie类的Genres属性可写:
public List<Genres> Genres { get; set; } = new();
- 在你的
DbContext子类的OnModelCreating方法中添加值转换配置,把流派列表转为逗号分隔的ID字符串存储:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Serie>() .Property(s => s.Genres) .HasConversion( // 存:把流派列表转成逗号分隔的ID字符串 list => string.Join(',', list.Select(g => g.Value)), // 读:把字符串拆分转回SmartEnum列表 str => str.Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(idStr => Genres.FromValue(int.Parse(idStr))) .ToList() ); }
内容的提问来源于stack exchange,提问作者user17441315
相关产品推荐
相关产品推荐

