如何使用Entity Framework 6 Code First设置默认值约束?

40

在旧版应用程序中,大多数字符串属性不能为null,并需要具有默认值string.empty。

我知道可以使用迁移来完成此操作,但我正在寻找一种使用流畅的配置界面来完成此操作的方法:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Properties<string>().Configure(c =>
        {
            c.HasMaxLength(255);

            if (!c.ClrPropertyInfo.IsDefined(typeof (NullableAttribute), false))
            {
                c.IsRequired();
                // I want to set a default value (string.empty) here.
            }
    }

有没有办法做到这一点,或者我注定要在实体构造函数中初始化所有字符串?


在实体构造函数中设置它怎么样? - Old Geezer
@老大爷,我正在处理这个问题,但它对我来说并没有解决问题。 - Mason240
只是额外补充一下:由于EF 6不支持此操作,且我不想在构造函数中设置默认值,因此我使用SQL设置了默认约束,至少对于使用模型优先的单元测试。每次我创建DBContext实例后都会发生这种情况,但至少对于单元测试来说,这是一个解决方法。 - Jürgen Bayer
6个回答

54

很遗憾,现在的答案是“不行”。

但是您可以更好地支持默认值投票。

编辑 2015年3月30日: 它将出现在 EF7 中...在 Code First 中支持数据库默认值

编辑 2017年1月30日:默认数据库值的通用支持已成为EF Core(EF7的新名称)的一部分... 默认值

编辑 2018年1月17日:我不确定为什么有人评论说EF7仍然是“一纸空文”。EF7(改名为EF Core)于2016年6月27日发布,并使用类似于FluentAPI的方法支持在Code First中设置默认值:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Rating)
        .HasDefaultValue(3);
}

EF Core 2.0发布于2017年8月14日。


6
EF7只是一厢情愿的幻想,无法用于生产。我们现在需要的是EF6! - Dave
@Sabre,为什么它不能用?你遇到了什么问题? - Colin
3
EF Core团队承认在它取代EF6成为"推荐版本"之前还有很多功能缺失:https://github.com/aspnet/EntityFrameworkCore/wiki/roadmap - Sabre
1
我感到震惊。EF已经存在了10年。当我设计数据库时,最基本的事情就是设置默认值。这个功能应该从第1版开始就存在,也就是10年前。相反,EF团队花费了所有时间来尝试使EF成为宇宙谜题的答案;当然,他们失败了。不适合目的。 - user1040323
有没有办法将它们链接起来,以便在需要设置同一实体的多个属性时使用?为同一实体创建大量这些似乎很愚蠢。 - Post Impatica
显示剩余2条评论

22

现在的答案是

AddColumn("[table name]", 
          "[column name]", 
          c => c.Boolean(nullable: false, defaultValue: false));

2
谢谢。我们最终转换到了NHibernate,但希望这个答案能帮助其他人。 - CB-Dan
47
为什么DbMigration.AddColumn方法被标记为答案,当问题中说:“我知道可以使用迁移来完成这个操作,但我正在寻找一种使用流畅的配置界面来完成这个操作的方式”? - Colin
8
同意。这个答案并没有回答问题。 - Stephen Holt
3
我同意,它不应该被选为答案。但也许它能帮助其他人。 我不知道是否可以取消选定答案。 目前更好的答案是@Colin的。 - Gh61

6
您可以在构造函数中设置默认值。
class Foo : Model
{
    public bool DefaultBool { get; set; }

    public Foo()
    {
        DefaultBool = true;
    }
}

当您创建一个新的Foo时,它将为属性DefaultBool设置真值。这不是默认约束,但它有效。


4
这完全没有回答问题。OP和其他人(包括我自己)来这里是想找出如何在表格上设置默认约束。 - async
1
只有EF7支持默认约束,这就是我使用此模式进行回答的原因。在使用先前的EF版本时,这是一种解决方法。顺便说一句,我说过“这不是默认约束”。 - Ariel Moraes

1
这是我对这个问题的回答。在 ef Core 3.1+ 中,您可以定义一个扩展方法,如下所示:
public static void AddDefaultValueSqlConvention(this ModelBuilder modelBuilder, string propertyName, Type propertyType, string defaultValueSql)
    {
        foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
        {
            IMutableProperty property = entityType.GetProperties().SingleOrDefault(p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));
            if (property != null && property.ClrType == propertyType)
                property.SetDefaultValueSql(defaultValueSql);
        }
    }

然后您可以这样使用这个扩展方法:
public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {

        base.OnModelCreating(builder);

        builder.AddDefaultValueSqlConvention("Version",typeof (int), "0" );
        builder.AddDefaultValueSqlConvention("CreateDate",typeof (DateTime), "GetDate()" );

    }
}

所有属性为“版本(Version)”且默认值设置为“0”的实体,以及所有属性为“创建日期(CreateDate)”且默认值设置为当前“日期时间(DateTime)”的实体。
如果有帮助,请投票支持。

-2

我在这里找到了这个例子

public class Person {
    private const int DEFAULT_AGE = 18;
    private int _age = DEFAULT_AGE;
    [DefaultValue(DEFAULT_AGE)]
    public int Age {
        get { return _age; }
        set { _age = value; }
    }
}

-6
我发现只需在实体属性上使用自动属性初始化程序即可完成工作。
例如:
public class Thing {
    public bool IsBigThing{ get; set; } = false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接