如何让EF Core数据库首次使用枚举?

Bas*_*bus 15 c# entity-framework-core

我正在使用EF Core和数据库优先方法,使用"Scaffold-DbContext"命令生成我的DbContext/Entities.

我怎样才能指导脚手架的DbContext某一个领域在一定的表格应该生成代码,使用枚举,而不是仅仅一个int?

以下是您在常规EF中的使用方法:https: //www.devu.com/cs-asp/lesson-69-mapping-enum-types-entity-properties-framework-designer/

此枚举已在代码中定义:

public enum StateEnum {
  Ok = 1,
  Fail = 2
}
Run Code Online (Sandbox Code Playgroud)

这就是Scaffold-DbContext给我的

public partial class Foo
{
    public int Id { get; set; }
    public int State { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这就是我想要它创建的:

public partial class Foo
{
    public int Id { get; set; }
    public StateEnum State { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

MrK*_*shi 21

EF Core 2.1中的值转换是否符合您的需求?

https://docs.microsoft.com/en-us/ef/core/modeling/value-conversions

快速示例:

  entity.Property(e => e.MyEnumField)
            .HasMaxLength(50)
            .HasConversion(
                v => v.ToString(),
                v => (MyEnum)Enum.Parse(typeof(MyEnum),v))
                .IsUnicode(false);
Run Code Online (Sandbox Code Playgroud)

  • OnModelCreating 不是这里的问题,因为在它的末尾,有一个 OnModelCreatingPartial 部分方法,因此您可以在那里添加配置(在单独的文件中)。这里的问题是您需要将属性类型(在您的实体中)定义为枚举。您无法执行此操作,因为该实体是在问题中使用 Scaffold-DbContext 生成的。并且生成后完成的每个手动修改都会在重新执行 Scaffold-DbContext 后被覆盖所以对我来说,这并不能回答问题 (5认同)
  • 这确实有效,但没有考虑OP使用Scaffold命令的原始要求,该命令将在每次运行时覆盖“OnModelCreating”方法的内容。 (2认同)

小智 12

接受的答案并不能解决问题。问题是“我如何指示 Scaffold-DbContext 某个表中的某个字段应该生成代码以使用 Enum 而不仅仅是 int?” 许多答案都指出,Entity Framework Core 2.1 现在支持值转换。如果您使用代码优先而不是数据库优先,那么这很有用。Scaffold-DbContext 每次都会覆盖 DBContext。就我个人而言,我对枚举作为数据库中的整数没有问题。但我不想在代码中使用整数。

你可以

  1. 更改 DBContext 以使用 ValueConversion。每次搭建脚手架时,您都会丢失该代码。
  2. 将实体中的整数更改为特定的枚举。它工作得很好,但当你搭建脚手架时,你也会失去它。
  3. 创建一个分部类,在其中创建名为 GetStateEnum() 和 SetStateEnum(StateEnum stateEnum) 等的方法。它非常冗长,但它将保留在脚手架之间。
  4. 有一种叫做源生成器的东西也许可以在将来解决这个问题。我还没有找到一个简单的解决方案。

我选择了替代方案 2。这是迄今为止我发现的最简单的一种,并且使用 git-compare 恢复类非常容易。我可以在一分钟内更改我的所有枚举。

如果有人有更好的解决方案。请告诉我。


A.J*_*uer 11

因为标题问题,我来到这里.不确定这是否适用于"Scaffold-DbContext",但它在DbContext(Microsoft.EntityFrameworkCore 2.0.1.0)中通过显式设置枚举的基本类型,即使枚举元素的默认基础类型为int也是如此.您也可以使用Fluent API来设置默认值(尤其是枚举以1开头的情况).

public enum StateEnum : int
{
    Ok = 1,
    Fail = 2
}
Run Code Online (Sandbox Code Playgroud)

枚举的已批准类型是byte,sbyte,short,ushort,int,uint,long或ulong.

所以我认为这适用于任何这些.枚举(C#参考)

public class MyDbContext : DbContext
{      
    protected override void OnModelCreating(ModelBuilder builder) 
    {
        builder.Entity<Foo>().Property(x => x.State).HasDefaultValue(StateEnum.Ok);
    }
}
Run Code Online (Sandbox Code Playgroud)


Dej*_*jan 10

从Entity Framework Core 2.1开始,EF支持Value Conversions以专门解决需要将属性映射到不同类型以进行存储的方案.

特别是对于Enums,您可以使用提供的EnumToStringConverterEnumToNumberConverter.

  • Scaffold-DbContext 将创建/覆盖我的 DbContext,因此它会覆盖“OnModelCreating”,您如何处理? (8认同)
  • @jsgoupil 在 OnModelCreating 的末尾有一个 OnModelCreatingPartial 。它的目的正是您想要实现的 (7认同)
  • 我不同意。枚举是CODE,因此没有数据库表示形式,否则您可以简单地向数据库中添加另一个值,这将使该代码无效,因为该枚举值未知。 (4认同)
  • 所有这些答案的问题在于它们将枚举存储为枚举父表的字符串或数字列。从数据库的角度来看,这是错误的。从数据库的角度来看,该枚举应作为 ID 字段存储在父表中,该父表通过外键引用查找表。 (3认同)
  • 最后!谢谢! (2认同)
  • 但是,这里有一个很大的警告:“使用值转换可能会影响EF Core将表达式转换为SQL的能力。在这种情况下,将记录一条警告。正在考虑删除这些限制以用于将来的发行版。” https: //docs.microsoft.com/zh-CN/ef/core/modeling/value-conversions (2认同)