代码优先迁移:如何为新属性设置默认值?

时间:2015-06-24 12:01:24

标签: c# .net entity-framework entity-framework-6 ef-migrations

我使用EF6在我的数据库中存储report类的实例。数据库已包含数据。假设我想将属性添加到report

public class report {
    // ... some previous properties

    // ... new property:
    public string newProperty{ get; set; }
}

现在,如果我转到包管理器控制台并执行

add-migration Report-added-newProperty
update-database

我会在' /迁移'中获取一个文件将newProperty列添加到表中的文件夹。这很好用。但是,对于数据库中较旧的条目,newProperty的值现在为空字符串。但我希望它是,例如," old"。

所以我的问题是:如何在迁移脚本(或其他地方)中为新属性(任何类型)设置默认值?

5 个答案:

答案 0 :(得分:54)

如果您看到生成的迁移代码,则会看到AddColumn

AddColumn("dbo.report", "newProperty", c => c.String(nullable: false));

您可以添加defaultValue

AddColumn("dbo.report", "newProperty", 
           c => c.String(nullable: false, defaultValue: "old"));

或添加defaultValueSql

AddColumn("dbo.report", "newProperty",
           c => c.String(nullable: false, defaultValueSql: "GETDATE()"));

答案 1 :(得分:5)

您必须更改迁移脚本中的行,该行添加属性/列,如下所示:

AddColumn("dbo.reports", "newProperty", c => c.String(nullable: false, defaultValue: "test"));

答案 2 :(得分:3)

希望它可以帮助某人。将先前答案中的所有内容放在一起(使用布尔属性的示例)

1)向实体添加新属性。

var obj = { ob1 : {"val1" : "test1", "val1" : "test1"},
            ob2 : ["v2", "v3", "v4"]
          };

for (var property in obj){
if (typeof obj[property] !=='string' || obj[property] === ""){
console.log(property + ' is empty or not a string!');
 }};

2)运行以下命令以在迁移中添加新更改。

/// <summary>
/// Determines if user is enabled or not. Default value is true
/// </summary>
public bool IsEnabled { get; set; }

3)从上面的命令创建一个迁移文件,打开该文件。

enter image description here

4)设置默认值。

add-migration addIsEnabledColumn

答案 3 :(得分:0)

我已通过覆盖 SaveChanges 方法解决了此问题。请参阅下面的解决方案。

  1. 解决方案说明

    i)覆盖DbContext类中的SaveChanges方法。

    public override int SaveChanges()
    {
        return base.SaveChanges();
    }
    

    ii)编写逻辑以设置默认值

    public override int SaveChanges()
    {
        //set default value for your property
        foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("YOUR_PROPERTY") != null))
        {
            if (entry.State == EntityState.Added)
            {
                if (entry.Property("YOUR_PROPERTY").CurrentValue == null)
                    entry.Property("YOUR_PROPERTY").CurrentValue = YOUR_DEFAULT_VALUE;
            }
        }
    
        return base.SaveChanges();
    }
    
  2. 示例

    public override int SaveChanges()
    {
        //set default value for RegistedDate property
        foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("RegistedDate") != null))
        {
            if (entry.State == EntityState.Added)
            {
                if ((DateTime)entry.Property("RegistedDate").CurrentValue == DateTime.MinValue)
                    entry.Property("RegistedDate").CurrentValue = DateTime.Now;
            }
        }
    
        //set default value for IsActive property
        foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("IsActive") != null))
        {
            if (entry.State == EntityState.Added)
            {
                if(entry.Property("IsActive").CurrentValue == null)
                    entry.Property("IsActive").CurrentValue = false;
            }
        }
    
        return base.SaveChanges();
    }
    

答案 4 :(得分:-5)

我发现只在实体属性上使用Auto-Property Initializer就足以完成工作。

例如:

public class Thing {
    public bool IsBigThing { get; set; } = false;
}