代码优先迁移:如何为新 属性 设置默认值?
Code-first migration: How to set default value for new property?
我正在使用 EF6 在我的数据库中存储 report
class 的实例。数据库已包含数据。假设我想添加一个 属性 到 report
,
public class report {
// ... some previous properties
// ... new property:
public string newProperty{ get; set; }
}
现在,如果我转到程序包管理器控制台并执行
add-migration Report-added-newProperty
update-database
我将在“/Migrations”文件夹中获取一个文件,将 newProperty
列添加到 table。这很好用。但是,在数据库中的旧条目中,newProperty
的值现在是一个空字符串。但我希望它是,例如 "old"。
所以我的问题是:如何在迁移脚本(或其他地方)中为新属性(任何类型)设置默认值?
如果您看到生成的迁移代码,您将看到 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()"));
您必须更改迁移脚本中添加 property/column 的行,如下所示:
AddColumn("dbo.reports", "newProperty", c => c.String(nullable: false, defaultValue: "test"));
我发现仅在实体 属性 上使用 Auto-属性 Initializer 就足以完成工作。
例如:
public class Thing {
public bool IsBigThing { get; set; } = false;
}
希望对大家有所帮助。将之前答案的所有内容放在一起 (使用布尔值 属性 的示例):
1) 添加一个新的属性实体。
/// <summary>
/// Determines if user is enabled or not. Default value is true
/// </summary>
public bool IsEnabled { get; set; }
2) 运行 下面的命令在迁移中添加新的更改。
add-migration addIsEnabledColumn
3) 从上面的命令创建了一个迁移文件,打开该文件。
4) 设置默认值。
public override void Up()
{
AddColumn(
"dbo.AspNetUsers",
"IsEnabled",
c => c.Boolean(
nullable: false,
defaultValue: true
)
);
}
我已经通过覆盖 SaveChanges 方法解决了这个问题。请参阅下面的解决方案。
解法详解
i) 覆盖 DbContext 中的 SaveChanges 方法 class。
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();
}
例子
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();
}
我正在使用 EF6 在我的数据库中存储 report
class 的实例。数据库已包含数据。假设我想添加一个 属性 到 report
,
public class report {
// ... some previous properties
// ... new property:
public string newProperty{ get; set; }
}
现在,如果我转到程序包管理器控制台并执行
add-migration Report-added-newProperty
update-database
我将在“/Migrations”文件夹中获取一个文件,将 newProperty
列添加到 table。这很好用。但是,在数据库中的旧条目中,newProperty
的值现在是一个空字符串。但我希望它是,例如 "old"。
所以我的问题是:如何在迁移脚本(或其他地方)中为新属性(任何类型)设置默认值?
如果您看到生成的迁移代码,您将看到 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()"));
您必须更改迁移脚本中添加 property/column 的行,如下所示:
AddColumn("dbo.reports", "newProperty", c => c.String(nullable: false, defaultValue: "test"));
我发现仅在实体 属性 上使用 Auto-属性 Initializer 就足以完成工作。
例如:
public class Thing {
public bool IsBigThing { get; set; } = false;
}
希望对大家有所帮助。将之前答案的所有内容放在一起 (使用布尔值 属性 的示例):
1) 添加一个新的属性实体。
/// <summary>
/// Determines if user is enabled or not. Default value is true
/// </summary>
public bool IsEnabled { get; set; }
2) 运行 下面的命令在迁移中添加新的更改。
add-migration addIsEnabledColumn
3) 从上面的命令创建了一个迁移文件,打开该文件。
4) 设置默认值。
public override void Up()
{
AddColumn(
"dbo.AspNetUsers",
"IsEnabled",
c => c.Boolean(
nullable: false,
defaultValue: true
)
);
}
我已经通过覆盖 SaveChanges 方法解决了这个问题。请参阅下面的解决方案。
解法详解
i) 覆盖 DbContext 中的 SaveChanges 方法 class。
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(); }
例子
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(); }