entity framework6代码优先默认值

有没有“优雅”的方式给特定的财产一个默认值?

也许通过DataAnnotations,如下所示:

[DefaultValue("true")] public bool Active { get; set; } 

谢谢。

您可以通过手动编辑代码首先进行迁移:

 public override void Up() { AddColumn("dbo.Events", "Active", c => c.Boolean(nullable: false, defaultValue: true)); } 

已经有一段时间了,但为别人留下一张纸条。 我实现了一个属性需要什么,我用我想要的属性装饰我的模型类字段。

 [SqlDefaultValue(DefaultValue = "getutcdate()")] public DateTime CreatedDateUtc { get; set; } 

得到这两篇文章的帮助:

  • EF在CodePlex上
  • 安迪·梅哈里克的博客

我做了什么:

定义属性

 [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class SqlDefaultValueAttribute : Attribute { public string DefaultValue { get; set; } } 

在上下文的“OnModelCreating”中

 modelBuilder.Conventions.Add( new AttributeToColumnAnnotationConvention<SqlDefaultValueAttribute, string>("SqlDefaultValue", (p, attributes) => attributes.Single().DefaultValue)); 

在自定义的SqlGenerator中

 private void SetAnnotatedColumn(ColumnModel col) { AnnotationValues values; if (col.Annotations.TryGetValue("SqlDefaultValue", out values)) { col.DefaultValueSql = (string)values.NewValue; } } 

然后在迁移configuration构造函数中,注册自定义SQL生成器。

 SetSqlGenerator("System.Data.SqlClient", new HarmonyMigrationSqlGenerator()); 

上述答案确实有帮助,但只提供了部分解决scheme。 主要的问题是,只要删除默认值属性,数据库中列的约束就不会被删除。 所以以前的默认值仍然会保留在数据库中。

这是一个完整的解决scheme,包括删除属性删除的SQL约束。 我也重新使用.NET Framework的本地DefaultValue属性。

用法

 [DatabaseGenerated(DatabaseGeneratedOption.Computed)] [DefaultValue("getutcdate()")] public DateTime CreatedOn { get; set; } 

为此,您需要更新IdentityModels.csConfiguration.cs文件

IdentityModels.cs文件

在你的ApplicationDbContext类中添加/更新这个方法

 protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); var convention = new AttributeToColumnAnnotationConvention<DefaultValueAttribute, string>("SqlDefaultValue", (p, attributes) => attributes.SingleOrDefault().Value.ToString()); modelBuilder.Conventions.Add(convention); } 

Configuration.cs文件

通过注册自定义的Sql生成器来更新你的Configuration类的构造函数,如下所示:

 internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext> { public Configuration() { // DefaultValue Sql Generator SetSqlGenerator("System.Data.SqlClient", new DefaultValueSqlServerMigrationSqlGenerator()); } } 

接下来,添加自定义的Sql生成器类(您可以将其添加到Configuration.cs文件或单独的文件)

 internal class DefaultValueSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator { private int dropConstraintCount = 0; protected override void Generate(AddColumnOperation addColumnOperation) { SetAnnotatedColumn(addColumnOperation.Column, addColumnOperation.Table); base.Generate(addColumnOperation); } protected override void Generate(AlterColumnOperation alterColumnOperation) { SetAnnotatedColumn(alterColumnOperation.Column, alterColumnOperation.Table); base.Generate(alterColumnOperation); } protected override void Generate(CreateTableOperation createTableOperation) { SetAnnotatedColumns(createTableOperation.Columns, createTableOperation.Name); base.Generate(createTableOperation); } protected override void Generate(AlterTableOperation alterTableOperation) { SetAnnotatedColumns(alterTableOperation.Columns, alterTableOperation.Name); base.Generate(alterTableOperation); } private void SetAnnotatedColumn(ColumnModel column, string tableName) { AnnotationValues values; if (column.Annotations.TryGetValue("SqlDefaultValue", out values)) { if (values.NewValue == null) { column.DefaultValueSql = null; using (var writer = Writer()) { // Drop Constraint writer.WriteLine(GetSqlDropConstraintQuery(tableName, column.Name)); Statement(writer); } } else { column.DefaultValueSql = (string)values.NewValue; } } } private void SetAnnotatedColumns(IEnumerable<ColumnModel> columns, string tableName) { foreach (var column in columns) { SetAnnotatedColumn(column, tableName); } } private string GetSqlDropConstraintQuery(string tableName, string columnName) { var tableNameSplittedByDot = tableName.Split('.'); var tableSchema = tableNameSplittedByDot[0]; var tablePureName = tableNameSplittedByDot[1]; var str = $@"DECLARE @var{dropConstraintCount} nvarchar(128) SELECT @var{dropConstraintCount} = name FROM sys.default_constraints WHERE parent_object_id = object_id(N'{tableSchema}.[{tablePureName}]') AND col_name(parent_object_id, parent_column_id) = '{columnName}'; IF @var{dropConstraintCount} IS NOT NULL EXECUTE('ALTER TABLE {tableSchema}.[{tablePureName}] DROP CONSTRAINT [' + @var{dropConstraintCount} + ']')"; dropConstraintCount = dropConstraintCount + 1; return str; } } 

您的模型属性不必是“自动属性”即使这很容易。 而DefaultValue属性实际上只是信息元数据这里接受的答案是构造函数方法的一种替代方法。

 public class Track { private const int DEFAULT_LENGTH = 400; private int _length = DEFAULT_LENGTH; [DefaultValue(DEFAULT_LENGTH)] public int LengthInMeters { get { return _length; } set { _length = value; } } } 

 public class Track { public Track() { LengthInMeters = 400; } public int LengthInMeters { get; set; } } 

这仅适用于使用此特定类创build和使用数据的应用程序。 通常这是不是一个问题,如果数据访问代码是集中的。 要更新所有应用程序的值,您需要configuration数据源以设置默认值。 Devi的答案显示了如何使用迁移,sql或数据源所说的任何语言来完成。

我做了什么,我在实体的构造函数中初始化了值

注意:DefaultValue属性不会自动设置你的属性的值,你必须自己做

@SedatKapanoglu发表评论后,我join了所有我的方法,因为他是正确的,只是使用stream利的API不起作用。

1-创build自定义代码生成器并覆盖为ColumnModel生成。

  public class ExtendedMigrationCodeGenerator : CSharpMigrationCodeGenerator { protected override void Generate(ColumnModel column, IndentedTextWriter writer, bool emitName = false) { if (column.Annotations.Keys.Contains("Default")) { var value = Convert.ChangeType(column.Annotations["Default"].NewValue, column.ClrDefaultValue.GetType()); column.DefaultValue = value; } base.Generate(column, writer, emitName); } } 

2-分配新的代码生成器:

 public sealed class Configuration : DbMigrationsConfiguration<Data.Context.EfSqlDbContext> { public Configuration() { CodeGenerator = new ExtendedMigrationCodeGenerator(); AutomaticMigrationsEnabled = false; } } 

3-使用stream利的API创build注释:

 public static void Configure(DbModelBuilder builder){ builder.Entity<Company>().Property(c => c.Status).HasColumnAnnotation("Default", 0); } 

只需重载Model类的默认构造函数,并传递您可能使用或不可使用的任何相关参数。 通过这个,你可以轻松地提供属性的默认值。 下面是一个例子。

 using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Aim.Data.Domain { [MetadataType(typeof(LoginModel))] public partial class Login { public Login(bool status) { this.CreatedDate = DateTime.Now; this.ModifiedDate = DateTime.Now; this.Culture = "EN-US"; this.IsDefaultPassword = status; this.IsActive = status; this.LoginLogs = new HashSet<LoginLog>(); this.LoginLogHistories = new HashSet<LoginLogHistory>(); } } public class LoginModel { [Key] [ScaffoldColumn(false)] public int Id { get; set; } [Required] public string LoginCode { get; set; } [Required] public string Password { get; set; } public string LastPassword { get; set; } public int UserGroupId { get; set; } public int FalseAttempt { get; set; } public bool IsLocked { get; set; } public int CreatedBy { get; set; } public System.DateTime CreatedDate { get; set; } public Nullable<int> ModifiedBy { get; set; } public Nullable<System.DateTime> ModifiedDate { get; set; } public string Culture { get; set; } public virtual ICollection<LoginLog> LoginLogs { get; set; } public virtual ICollection<LoginLogHistory> LoginLogHistories { get; set; } } } 

我承认,我的方法逃避了“Code First”方法。 但是,如果你有能力改变表格中的默认值,那么要比上面的长度要简单得多…我只是懒得做所有的工作!

这几乎看起来好像海报原创的想法会起作用:

 [DefaultValue(true)] public bool IsAdmin { get; set; } 

我以为他们只是犯了添加引号的错误,但唉,没有这样的直觉。 其他的build议对我来说太过分了(如果我拥有进入桌面进行修改的权限,那么在任何情况下开发人员都不是这样)。 最后,我只是以老式的方式做到了。 我在SQL Server表中设置了默认值…我的意思真的够了! 注:我进一步testing做一个添加迁移和更新数据库和更改卡住。 在这里输入图像描述

嗯…我先做数据库,在这种情况下,这实际上更容易。 EF6的权利? 只要打开你的模型,右键点击你想设置的默认列,select属性,你会看到一个“DefaultValue”字段。 只需填写并保存。 它会为你设置代码。

你的里程可能会在代码上有所不同,但我没有与之合作。

许多其他解决scheme的问题是,虽然它们可能在初始阶段工作,但只要重新构build模型,就会抛出您插入到机器生成文件中的任何自定义代码。

此方法通过向edmx文件添加一个额外的属性来工作:

 <EntityType Name="Thingy"> <Property Name="Iteration" Type="Int32" Nullable="false" **DefaultValue="1"** /> 

并通过添加必要的代码给构造函数:

 public Thingy() { this.Iteration = 1; 

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

例如:

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

在MSSQL Server中为表中的列设置默认值,并在类代码中添加属性,如下所示:

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]

为同一个财产。

我不知道这些答案是从哪里来的!

让我们考虑你有一个名为Products的类名,你有一个IsActive字段。 只是你需要一个创build构造函数:

 Public class Products { public Products() { IsActive = true; } public string Field1 { get; set; } public string Field2 { get; set; } public bool IsActive { get; set; } } 

那么你的IsActive默认值是True!

Edite

如果你想用SQL来做这个事情,可以使用这个命令:

 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .Property(b => b.IsActive) .HasDefaultValueSql("true"); }