Entity Framework 6 Сначала код Значение по умолчанию

есть ли «элегантный» способ присвоить определенному свойству значение по умолчанию?

Может быть, DataAnnotations, что-то вроде:

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

Спасибо.

Вы можете сделать это, вручную изменив первую миграцию кода:

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

Это было какое-то время, но оставив записку для других. Я достиг того, что нужно с атрибутом, и я украсил поля classа модели этим атрибутом, как я хочу.

 [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("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; } } 

Затем в конструкторе конфигурации миграции зарегистрируйте собственный генератор SQL.

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

Вышеупомянутые ответы действительно помогли, но только доставили часть решения. Основная проблема заключается в том, что как только вы удалите атрибут значения по умолчанию, ограничение на столбец в базе данных не будет удалено. Таким образом, предыдущее значение по умолчанию все равно останется в базе данных.

Вот полное решение этой проблемы, включая устранение ограничений SQL при удалении атрибутов. Я также повторно использую собственный атрибут DefaultValue .NET Framework.

Применение

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

Для этого вам необходимо обновить файлы IdentityModels.cs и Configuration.cs

Файл IdentityModels.cs

Добавить / обновить этот метод в classе ApplicationDbContext

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

Файл Configuration.cs

Обновите конструктор classа Configuration , зарегистрировав собственный генератор Sql, например:

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

Затем добавьте собственный class генератора 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 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 = [email protected]"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; } } 

Это будет работать только для приложений, создающих и потребляющих данные с использованием этого конкретного classа. Обычно это не проблема, если код доступа к данным централизован. Чтобы обновить значение для всех приложений, вам необходимо настроить источник данных для установки значения по умолчанию. Ответ Devi показывает, как это можно сделать с помощью миграции, sql или любого другого языка, на котором говорит ваш источник данных.

Что я сделал, я инициализировал значения в конструкторе объекта

Примечание: атрибуты DefaultValue не будут автоматически устанавливать значения ваших свойств, вы должны сделать это самостоятельно

После комментария @SedatKapanoglu, я добавляю весь мой подход, который работает, потому что он прав, просто использование свободного API не работает.

1- Создать собственный генератор кода и переопределить Generate для 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 { public Configuration() { CodeGenerator = new ExtendedMigrationCodeGenerator(); AutomaticMigrationsEnabled = false; } } 

3- Используйте беглый api для создания annotations:

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

Просто перегрузите конструктор по умолчанию classа 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(); this.LoginLogHistories = new HashSet(); } } 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 ModifiedBy { get; set; } public Nullable ModifiedDate { get; set; } public string Culture { get; set; } public virtual ICollection LoginLogs { get; set; } public virtual ICollection LoginLogHistories { get; set; } } } 

Я не знаю, откуда берутся ответы!

Давайте рассмотрим, что у вас есть имя classа под названием Products, и у вас есть поле IsActive. просто нужно создать конструктор:

 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() .Property(b => b.IsActive) .HasDefaultValueSql("true"); } 

Я признаю, что мой подход избегает всего подхода «Code First». Но если у вас есть возможность просто изменить значение по умолчанию в самой таблице … это намного проще, чем длины, которые вы должны пройти выше … Я просто слишком ленив, чтобы делать все это!

Похоже, что оригинальная идея плакатов будет работать:

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

Я думал, что они просто допустили ошибку, добавив цитаты … но, увы, нет такой интуитивности. Другие предложения были для меня слишком большими (если у меня есть привилегии, необходимые для входа в таблицу и внесения изменений … где не каждый разработчик будет в любой ситуации). В конце концов я просто сделал это старомодным способом. Я установил значение по умолчанию в таблице SQL Server … Я имею в виду, действительно, уже достаточно! ПРИМЕЧАНИЕ. Я также тестировал выполнение добавления-миграции и базы данных обновлений и изменений. введите описание изображения здесь

Я обнаружил, что достаточно использовать Auto-Property Initializer для свойства entity, чтобы выполнить работу.

Например:

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

Хм … Сначала я делаю БД, и в этом случае это на самом деле намного проще. EF6 правильно? Просто откройте свою модель, щелкните правой кнопкой мыши на столбце, для которого вы хотите установить значение по умолчанию, выберите свойства, и вы увидите поле «DefaultValue». Просто заполните это и сохраните. Он настроит код для вас.

Ваш пробег может отличаться от кода, хотя я не работал с этим.

Проблема с множеством других решений заключается в том, что, хотя они могут работать на начальном этапе, как только вы перестраиваете модель, она выкинет любой пользовательский код, который вы вставляете в машинный файл.

Этот метод работает, добавляя дополнительное свойство в файл edmx:

   

И добавив необходимый код к конструктору:

 public Thingy() { this.Iteration = 1; 

Задайте значение по умолчанию для столбца в таблице на сервере MSSQL и в атрибуте добавления кода classа, например:

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]

для того же свойства.

  • Отображение представлений базы данных в EF 5.0 Code First w / Migrations
  • EF 4.1 загрузка фильтрованных дочерних коллекций, не работающих для многих-ко-многим
  • Entity Framework с NOLOCK
  • Рамификации DbSet.Create против нового объекта ()
  • Первые таблицы переходов EF5 и таблицы поиска
  • Тип или имя пространства имен «DbContext» не удалось найти
  • ключевое слово не поддерживается источник данных
  • Как хранить изображения с использованием кода Entity Framework First CTP 5?
  • Уникальные ограничения ключа для нескольких столбцов в Entity Framework
  • SqlException из Entity Framework - новая транзакция не допускается, поскольку в сеансе есть другие streamи
  • Организационно, где я должен ставить общие запросы при первом использовании кода Entity Framework?
  • Давайте будем гением компьютера.