首页 > 解决方案 > Enity Framework Core:处理大量类似枚举的字段

问题描述

我目前面临以下问题:我有一个LargeDataClass包含许多字段(200+)的模型类。其中许多字段(约 50-80)类似于枚举(即它们可以用 UI 中的某些选项集填写)。现在我的方法是将这些建模为枚举类,比如

[Table("tbl_enum_one")]
class EnumOne {
  public int ID { get; set; }
  public string Name { get; set; }
}

[Table("tbl_large_dataclass")]
class LargeDataClass {
   public EnumOne EnumOne { get; set; }
   public int EnumOneId { get; set; }
   //...
}

这具有易于扩展的主要优点(要在 UI 中添加下拉选项,只需向表中添加一行)。现在我面临一些担忧/问题:

  1. 当我从包含所有枚举字段的数据库中获取我的模型类LargeDataClass时,将会有很多连接(如上所述,这些字段中有 50 到 80 个)。我担心这会对查询性能产生很大影响。另外,由于要更新大量索引,创建/更新/删除可能会很慢。
  2. MySQL 甚至不会让我创建tbl_large_dataclass具有那么多 FK 的表(单个表上的索引太多)。

所以现在我正在考虑两个(在我看来真的很不幸)选项:

  1. 使用常规枚举,因此没有枚举类具有自己的表,将它们作为简单的 int/string 字段存储在数据库中。这根本不会引起性能问题,但不幸的是,“实时”可扩展性非常重要,所以这个选项只是最后的手段。

  2. 使用 Enum 类,但在 中只有枚举的 ID LargeDataClass,因此保留了这是来自数据库的外键机密的事实。如果我想在LargeDataClass某处显示一个对象,我将不得不单独获取枚举类。另外,我必须特别确保我只使用枚举表中真正存在的 Id。

我真的不确定这里最好的方法是什么。

标签: mysqlsqlentity-framework-core

解决方案


数据库不是对象存储,您必须相应地设计它。我已经改变了你的架构,只需要两个表来存储下拉值。

[Table("tbl_enum_type")]
public class EnumType {
  public int ID { get; set; } // PK
  public string Name { get; set; }
}

// PK (EnumTypeId, Id) - reusing the same index for dropdown generation
[Table("tbl_enum_value")]
public class EnumValue {
  public int ID { get; set; } 
  public string Name { get; set; }
  public int Order { get; set; } // for dropdown ordering
  public int EnumTypeId { get; set; } 
  public EnumType EnumType { get; set; }
}

// store only ID's, no FK
[Table("tbl_large_dataclass")]
public class LargeDataClass {
   public int EnumOneId { get; set; }    // EnumTypeId 1
   public int EnumSecondId { get; set; } // EnumTypeId 2
   //...
}

为了生成下拉列表,您必须以有用的结构将 EnumType 和 EnumValue 表缓存在内存中。

覆盖方法SaveChanges/SaveChangesAsync并根据缓存数据检查保存的 Id。

如果您的数据库是通过 SQL 更改的,这将无济于事,但在这里我们需要在性能和一致性之间进行权衡。可能好的触发器在这里可能会有所帮助。

更新:

考虑将 LargeDataClass 重构为两个表

[Table("tbl_option_bag")]
public class OptionBag {
   public int Id { get; set; }    
   public ICollection<Option> Options { get; set; } 
}

[Table("tbl_options")]
public class Option {
   public int Id { get; set; } 
   public int OptionBagId {get; set; }
   public int EnumTypeId { get; set; } 
   public int EnumId { get; set; } 
   //...
}

在这里,您可以使用 FK,并且可以在选择 Options 导航属性时生成 DTO。


推荐阅读