【问题标题】:Transition EF Core 3.1 to storing string enum values, rather than ints将 EF Core 3.1 转换为存储字符串枚举值,而不是整数
【发布时间】:2020-07-08 10:28:58
【问题描述】:

我想知道对于将枚举值存储为整数的现有数据库的问题是否有一个优雅的解决方案,但想要过渡到存储新记录的字符串,但将整数单独留在旧记录中。自然地,我们可以将列类型从 int 变为 string,而表示“Ready”的“2”仍然可以存储在字符串列中。..

是否有一种技术允许 EF 将“2”或“Ready”解析为 Status.Ready 中的 enum Status { Ready = 2 } ?我知道 EF Core 有一个可以理解 "Ready" -> Status.Ready 的 EnumStringConverter,但是有没有办法扩展或自定义它,以便它尝试双向解析 db 值? (“Ready”作为枚举元素名称 -> 成功,“2”作为枚举元素名称 -> 失败,“2”作为枚举元素值 -> 成功)我们是否会编写一个转换过程,例如检查数据库中的所有字符value 是数字,因此将其解析为值,否则将其解析为名称?

或者从使用整数转换为使用字符串的人是否也编写了大量迁移来更新每个枚举列中的每个值,以便所有现有的“2”都变成“就绪”?

【问题讨论】:

  • 但是,如果您从整数转换为字符串,您已经在更改列类型,对吧?这意味着重写整个现有表。如果您负担得起,那么现有数据的一次性UPDATE 似乎并不需要太多额外的努力。如果您现在将整数枚举值存储在字符串列中,情况会有所不同,但这很奇怪。以我的经验,为兼容目的支持“零碎转换”几乎总是比它的价值更麻烦,应该避免,除非批发转换成本太高(即停机时间太长)。
  • 你不能创建另一个表格,将数值与字符串表示相关联吗?
  • @Magnetron 我可以,但是这是“状态 2 又是什么意思?等一下……INNER JOIN Enums e ON e.Type = 'Status' and e.Value = mytable.Status WHERE e.Name = 'Ready'……为了几个字节,我希望清除未来的神奇数字数据库。我们所有的项目都是字符串枚举,除了这个项目被外包给从一开始就没有使用 EnumToStringConverter 的分包商......
  • @JeroenMostert 是一个有效的观点,尤其是考虑到我们有这么多 int enum 列,这可能是识别和更改列类型的编程练习。使用一些简单的查找/替换来解析 Enums.cs 以生成一堆 UPDATE 语句并作为迁移的一部分进行旧值的转换可能更容易 - 我仍然有兴趣知道是否有一种便宜的方法来制作 EF尝试将“2”转换为“Ready”,特别是如果我要调整模型构建器并制作所有枚举 EnumToStringConverter,我想可能是一个用于分阶段转换的自定义枚举

标签: c# enums entity-framework-core ef-core-3.1


【解决方案1】:

您可以使用custom converter,如下所示

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<MyEntity>()
        .Property(e => e.MyStatusColumn)
        .HasConversion(
            v => v.ToString(),
            v => int.TryParse(v, out int val) ? 
                 (Status)val : 
                 (Status)Enum.Parse(typeof(Status), v)
        );
}

【讨论】:

    【解决方案2】:

    根据我自己的实践,我将枚举值作为 int 存储在数据库中。为了在客户端进行演示,我做了以下技巧。

    在具有您的枚举属性 Status 的实体类中,创建另一个获取该枚举的字符串值的属性:

     public enum Status
     {
        None,
        Ready,
        InProcess,
        NotReady
     }
    
     public class Process
     {
        public int Id { get; set; }
        public Status Status { get; set; }
        public string GetStatus 
        {
            get
            {
                return Status.ToString();
            }
        }
     }
    

    这里,如果您的 Process 对象的 Status 属性值为 1,则 GetStatus 属性只返回 Ready 字符串。

    希望,这能回答你的问题。

    【讨论】:

      猜你喜欢
      • 2018-05-23
      • 1970-01-01
      • 2014-09-27
      • 2020-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      • 2012-04-30
      相关资源
      最近更新 更多