首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Entity Framework在保存时将枚举重置为默认值

为什么Entity Framework在保存时将枚举重置为默认值
EN

Stack Overflow用户
提问于 2021-01-07 01:27:02
回答 2查看 281关注 0票数 1

我正在调试以下令人费解的行为。我有一个包含[Required]枚举的实体ExampleEntity,出于迁移原因,它有一个默认值。在插入新的ExampleEntity时,我指定了此字段应采用的值。通过在调试器中进行检查,可以发现该值已在DbSet的本地版本中正确设置。但是,每当我对上下文调用SaveChanges()时,枚举值都会被重置为配置的默认值。

模型:

代码语言:javascript
复制
public enum ExampleEnum
{
    Mecury,
    Venus,
    Earth,
    Mars
}

internal class ExampleEntity
{
    public int id { get; set; }

    [Required]
    public ExampleEnum Val { get; set; }
}

internal class EFContext : DbContext
{
    public EFContext(DbContextOptions options) : base(options)
    {
    }

    public virtual DbSet<ExampleEntity> Ents { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
       modelBuilder.Entity<ExampleEntity>(entity =>
       {
            entity.Property(e => e.Val).HasDefaultValue(ExampleEnum.Earth);
       });
    }
}

测试代码:

代码语言:javascript
复制
class Program
{
    private static DbConnection CreateInMemoryDatabase()
    {
        var connection = new SqliteConnection("Filename=:memory:");
        connection.Open();
        return connection;
    }

    static void Main(string[] args)
    {
        var ContextOptions = new DbContextOptionsBuilder<EFContext>()
                .UseSqlite(CreateInMemoryDatabase())
                .Options;

        using (var context = new EFContext(ContextOptions))
        {
            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();
        }

        using (var db = new EFContext(ContextOptions))
        {
            var newEntity = new ExampleEntity
            {
               Val = ExampleEnum.Mecury,
            };
            db.Ents.Add(newEntity);
            db.SaveChanges();
        }

        using (var db = new EFContext(ContextOptions))
        {
            var savedEnt = db.Ents.First();
            Console.WriteLine(savedEnt.Val.ToString());
        }
    }
}

我期望打印的值是Mercury,但它打印出配置的默认Earth。我可以在保存更改后解决此问题,将Val设置为所需的值:

代码语言:javascript
复制
var newEntity = new ExampleEntity
{
   Val = ExampleEnum.Mecury,
};
db.Ents.Add(newEntity);
db.SaveChanges();
newEnttity.Val = ExampleEnum.Mecury;
db.SaveChanges()
EN

回答 2

Stack Overflow用户

发布于 2021-01-07 01:27:02

该问题是由使用Mecury (0)的默认值引起的。Entity Framework可能无法区分未初始化的枚举和故意设置为0的枚举,因此它假定是前者并设置为默认值。

可能最简单的修复方法是使用0(第一个枚举值)作为默认值。在这种情况下,将枚举重新排序为:

代码语言:javascript
复制
Earth
Mecury
Venus
Mars
票数 1
EN

Stack Overflow用户

发布于 2021-01-07 08:46:35

重新排序枚举,这会在您决定更改代码中的默认枚举时产生一些问题,然后以使现有数据无效结束。相反,我建议对声明的枚举始终使用NotSet/None默认值:

代码语言:javascript
复制
public enum ExampleEnum
{
    NotSet = 0,
    Mecury,
    Venus,
    Earth,
    Mars
}

对于实体,我建议在实体属性上设置默认值。这样,新实体被初始化,并且在被持久化之前和之后都处于有效状态:

代码语言:javascript
复制
internal class ExampleEntity
{
    public int id { get; set; }

    [Required]
    public ExampleEnum Val { get; set; } = ExampleEnum.Earth;
}

当没有提供值时,HasDefaultValue只是告诉EF期望在列上设置一个DefaultValue。在应用CodeFirst的情况下,您指定的值将设置为默认值。它似乎确实引入了一个拦截器来将该属性更新为默认值(0),因为删除该HasDefaultValue配置将允许您使用新行保存原始Meruly值(0)。我在使用以下配置和不使用配置的情况下进行测试:

代码语言:javascript
复制
var test = new ExampleEntity { Val = ExampleEnum.Mars};
test.Val = ExampleEnum.Mercury;

这消除了忽略"set“的EF,因为枚举的类默认值仍然是(0 Mercury)。虽然您的配置和枚举声明的Mercury =0,但由于相同的原因,上面的测试仍然失败。删除默认设置和上述设置的配置按预期工作。

总之,我建议将枚举默认值设置为类似于"NotSet“的值,然后在属性上使用初始化器,以获得所需的默认值,而EF只关心底层架构。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65600481

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档