Entity Framework 마이그레이션의 필수 필드에 대한 기본값은 무엇입니까?


91

ASP.NET MVC 응용 프로그램[Required] 에서 내 모델 중 하나에 데이터 주석을 추가했습니다 . 마이그레이션을 만든 후 명령을 실행 하면 다음 오류가 발생합니다.Update-Database

'Director'열, 'MOVIES_cf7bad808fa94f89afa2e5dae1161e78.dbo.Movies'테이블에 NULL 값을 삽입 할 수 없습니다. 열은 널을 허용하지 않습니다. UPDATE가 실패합니다. 그 진술서는 만료되었습니다.

이는 Director열에 NULL이있는 일부 레코드 때문 입니다. 이러한 값을 일부 기본 (예 : "John Doe") 디렉터로 자동으로 변경하려면 어떻게해야합니까?

내 모델은 다음과 같습니다.

  public class Movie
    {
        public int ID { get; set; }
        [Required]
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Required]
        public string Genre { get; set; }

        [Range(1,100)]
        [DataType(DataType.Currency)]
        public decimal Price { get; set; }

        [StringLength(5)]
        public string Rating { get; set; }

        [Required]     /// <--- NEW
        public string Director { get; set; }
    }

내 최근 마이그레이션은 다음과 같습니다.

public partial class AddDataAnnotationsMig : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false));
        AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false));
        AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
        AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false));
    }

    public override void Down()
    {
        AlterColumn("dbo.Movies", "Director", c => c.String());
        AlterColumn("dbo.Movies", "Rating", c => c.String());
        AlterColumn("dbo.Movies", "Genre", c => c.String());
        AlterColumn("dbo.Movies", "Title", c => c.String());
    }
}

답변:


74

올바르게 기억하면 다음과 같이 작동합니다.

AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false, defaultValueSql: "'John Doe'"));

참고 : defaultValueSql 매개 변수 값은 약어 SQL 문으로 처리되므로 John Doe 예와 같이 필수 값이 사실상 문자열 인 경우 값을 작은 따옴표로 묶어야합니다.


9
나도 그렇게 생각했지만 기존 레코드에서는 작동하지 않는 것 같습니다. 그래서 여전히 오류가 발생합니다.
Andriy Drozdyuk 2012 년

@drozzy 아마도 다음과 같은 버그 일 수 있습니다. EF 4.3.1 마이그레이션 예외-AlterColumn defaultValueSql은 서로 다른 테이블에 대해 동일한 기본 제약 조건 이름을 만듭니다IS NULL . 쿼리 로 확인하여 행을 업데이트 할 수 있습니다 .
webdeveloper

흥미롭지 만 그들이 무슨 말을하는지 잘 모르겠습니다. 그러나 이것이 버그라면 그렇습니다.
Andriy Drozdyuk 2012 년

6
나는 그것이되어야한다고 생각한다 : "'John Doe'"-당신은 SQL 따옴표를 사용해야한다.
Sean

1
@webdeveloper, 버그라고 생각하지 않습니다. 왜 AlterColumn현재 값을 업데이트합니까? DDL (DML 아님) 명령입니다.
Anton

110

@webdeveloper 및 @Pushpendra의 답변 외에도 마이그레이션에 업데이트를 수동으로 추가하여 기존 행을 업데이트해야합니다. 예를 들면 :

public override void Up()
{
    Sql("UPDATE [dbo].[Movies] SET Title = 'No Title' WHERE Title IS NULL");
    AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false,defaultValue:"MyTitle"));
}

이는 AlterColumn열의 기본값을 테이블 사양의 특정 값으로 설정하는 DDL을 생성 하기 때문 입니다. DDL은 데이터베이스의 기존 행에 영향을주지 않습니다.

실제로 동시에 두 가지 변경을 수행하고 (기본값을 설정하고 열을 NOT NULL로 설정) 각각은 개별적으로 유효하지만 두 가지를 동시에 수행하므로 시스템이 ' 지능적으로 '당신의 의도를 깨닫고 모든 것을 설정 NULL 값을 기본값으로 하지만 항상 예상되는 것은 아닙니다.

열의 기본값 만 설정하고 NULL이 아니라고 가정합니다. 분명히 모든 NULL 레코드가 사용자가 제공 한 기본값으로 업데이트 될 것이라고 기대하지는 않습니다.

따라서 제 생각에는 이것은 버그가 아니며 EF가 명시 적으로 지시하지 않은 방식으로 데이터를 업데이트하는 것을 원하지 않습니다. 개발자는 데이터로 수행 할 작업에 대해 시스템에 지시 할 책임이 있습니다.


17
Google을 통해이 답변을 찾는 사람들을 위해 : EF6에서 이것을 시도했으며 업데이트 문이 더 이상 필요하지 않은 것 같습니다. 결국 그들은 그것을 버그로 간주했다고 생각합니다.
EPLKleijntjens 2014 년

3
나는 또한 그것을 보증 할 수 있습니다. nullable 필드에도 기본값이 필요한 경우 먼저 기본값을 사용하여 nullable이 아닌 값으로 변경 한 다음 다시 nullable로 변경하면됩니다. 당신이 :) 자식 클래스에 nullable이 아닌 필드를 추가 할 때 매우 편리합니다
WOUTER Schut

1
설명에 스팟. AlterColumn ()은 열 정의 만 변경합니다. 그것은 무엇이든지 기존 레코드에 영향을주지 않습니다
Korayem

10
public partial class AddDataAnnotationsMig : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false,defaultValue:"MyTitle"));
        AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false,defaultValue:"Genre"));
        AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
        AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false,defaultValue:"Director"));

    }

    public override void Down()
    {       
        AlterColumn("dbo.Movies", "Director", c => c.String());
        AlterColumn("dbo.Movies", "Rating", c => c.String());
        AlterColumn("dbo.Movies", "Genre", c => c.String());
        AlterColumn("dbo.Movies", "Title", c => c.String());       
    }
}

2
음 ... 고맙지 만 @webdeveloper의 답변과 어떻게 다른가요?
Andriy Drozdyuk 2012 년

1
기본값 매개 변수를 어디에 추가
해야하는지 알려주지 않습니다

1
@Pushpendra, 개발자가 옛날 옛적에 많이 알지 못했다는 사실을 잊는 경향이 있다는 것은 재밌습니다. 나는 모든 수준을 만족시키는 상세한 답변을 좋아합니다. 훌륭합니다!
usefulBee

5

이 옵션이 항상 주변에 있는지 확실하지 않지만 비슷한 문제가 발생하여 다음을 사용하여 수동 업데이트를 실행하지 않고 기본값을 설정할 수 있음을 발견했습니다.

defaultValueSql: "'NY'"

나는 값이되었다 제공 오류가있어 "NY"다음 나는 그들이 SQL 값을 기대하고 있음을 깨달았을 같은 "GETDATE()"내가 노력 있도록 "'NY'"하고 트릭 행한

전체 라인은 다음과 같습니다

AddColumn("TABLE_NAME", "State", c => c.String(maxLength: 2, nullable: false, defaultValueSql: "'NY'"));

이 답변 덕분에 올바른 방향으로 나아갔습니다.


2

EF Core 2.1부터 MigrationBuilder.UpdateData열을 변경하기 전에 값을 변경하는 데 사용할 수 있습니다 (원시 SQL을 사용하는 것보다 더 깔끔함).

protected override void Up(MigrationBuilder migrationBuilder)
{
    // Change existing NULL values to NOT NULL values
    migrationBuilder.UpdateData(
        table: tableName,
        column: columnName,
        value: valueInsteadOfNull,
        keyColumn: columnName,
        keyValue: null);

    // Change column type to NOT NULL
    migrationBuilder.AlterColumn<ColumnType>(
        table: tableName,
        name: columnName,
        nullable: false,
        oldClrType: typeof(ColumnType),
        oldNullable: true);
}

1

엔터티 속성에 Auto-Property Initializer를 사용하는 것만으로도 작업을 완료 할 수 있습니다.

예를 들면 :

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

2
좋은 대답 (도움이 됨)이지만 데이터베이스에 기본값을 추가하지 않고 코드에서 값을 설정합니다.
chris31389

바로 마이그레이션 chnages 후 데이터베이스에 기본값을 추가하지 않았습니다
Chetan Chaudhari

1

다른 많은 응답은 이러한 문제가 발생할 때 수동으로 개입하는 방법에 중점을 둡니다.

마이그레이션을 생성 한 후 마이그레이션에 대해 다음 변경 중 하나를 수행하십시오.

  1. defaultValue 또는 defaultSql 문을 포함하도록 열 정의를 수정합니다.
    AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false, default: ""));

  2. AlterColumn 앞에 SQL 문을 삽입하여 기존 열을 미리 채 웁니다.
    Sql("UPDATE dbo.Movies SET Director = '' WHERE Director IS NULL");

마이그레이션을 다시 스캐 폴드하면 마이그레이션 스크립트에 적용된 수동 변경 사항을 덮어 씁니다. 첫 번째 솔루션의 경우 마이그레이션 생성의 일부로 필드에 기본값을 자동으로 정의하도록 EF를 확장하는 것이 매우 쉽습니다.

참고 : EF는 각 RDBMS 공급자마다 기본값 구현이 다르기 때문에 자동으로이 작업을 수행하지 않습니다. 또한 각 행 삽입이 각 속성에 대한 현재 값을 제공하기 때문에 기본값이 순수 EF 런타임에서 의미가 적기 때문에이 작업을 자동으로 수행하지 않습니다. null 인 경우에도 기본값 제약 조건은 평가되지 않습니다.
이 AlterColumn 문은 기본 제약 조건이 적용되는 유일한 시간입니다. SQL Server 마이그레이션 구현을 디자인 한 팀의 우선 순위가 낮아진 것 같습니다.

다음 솔루션은 속성 표기법, 모델 구성 규칙 및 열 주석을 결합하여 메타 데이터를 통해 사용자 지정 마이그레이션 코드 생성기로 전달합니다. 속성 표기법을 사용하지 않는 경우 1 단계와 2 단계를 영향을받는 각 필드에 대한 유창한 표기법으로 바꿀 수 있습니다.
여기에는 많은 기술이 있습니다. 일부 또는 전부를 자유롭게 사용하십시오. 여기 모두에게 가치가 있기를 바랍니다.


  1. 기본값 선언
    사용할 기본값을 정의하기 위해 기존 속성을 생성하거나 용도를 변경합니다.이 예에서는 사용이 직관적이고 기존 속성이 존재할 가능성이 있으므로 ComponentModel.DefaultValueAttribute에서 상속하는 DefaultValue라는 새 속성을 생성합니다. 코드베이스는 이미이 속성을 구현합니다. 이 구현에서는이 특정 속성을 사용하여 날짜 및 기타 사용자 지정 시나리오에 유용한 DefaultValueSql에 액세스하기 만하면됩니다.

    이행

    [DefaultValue("Insert DefaultValue Here")]
    [Required]     /// <--- NEW
    public string Director { get; set; }
    
    // Example of default value sql
    [DefaultValue(DefaultValueSql: "GetDate()")]
    [Required]
    public string LastModified { get; set; }

    속성 정의

    namespace EFExtensions
    {
        /// <summary>
        /// Specifies the default value for a property but allows a custom SQL statement to be provided as well. <see cref="MiniTuber.Database.Conventions.DefaultValueConvention"/>
        /// </summary>
        public class DefaultValueAttribute : System.ComponentModel.DefaultValueAttribute
        {
            /// <summary>
            /// Specifies the default value for a property but allows a custom SQL statement to be provided as well. <see cref="MiniTuber.Database.Conventions.DefaultValueConvention"/>
            /// </summary>
            public DefaultValueAttribute() : base("")
            {
            }
    
            /// <i
            /// <summary>
            /// Optional SQL to use to specify the default value.
            /// </summary>
            public string DefaultSql { get; set; }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a Unicode character.
            /// </summary>
            /// <param name="value">
            /// A Unicode character that is the default value.
            /// </param>
            public DefaultValueAttribute(char value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using an 8-bit unsigned integer.
            /// </summary>
            /// <param name="value">
            /// An 8-bit unsigned integer that is the default value.
            /// </param>
            public DefaultValueAttribute(byte value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 16-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 16-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(short value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 32-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 32-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(int value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 64-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 64-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(long value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a single-precision floating point number.
            /// </summary>
            /// <param name="value">
            /// A single-precision floating point number that is the default value.
            /// </param>
            public DefaultValueAttribute(float value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a double-precision floating point number.
            /// </summary>
            /// <param name="value">
            /// A double-precision floating point number that is the default value.
            /// </param>
            public DefaultValueAttribute(double value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a System.Boolean value.
            /// </summary>
            /// <param name="value">
            /// A System.Boolean that is the default value.
            /// </param>
            public DefaultValueAttribute(bool value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a System.String.
            /// </summary>
            /// <param name="value">
            /// A System.String that is the default value.
            /// </param>
            public DefaultValueAttribute(string value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class.
            /// </summary>
            /// <param name="value">
            /// An System.Object that represents the default value.
            /// </param>
            public DefaultValueAttribute(object value) : base(value) { }
    
            /// /// <inheritdoc/>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class, converting the specified value to the specified type, and using an invariant
            /// culture as the translation context.
            /// </summary>
            /// <param name="type">
            /// A System.Type that represents the type to convert the value to.
            /// </param>
            /// <param name="value">
            /// A System.String that can be converted to the type using the System.ComponentModel.TypeConverter
            /// for the type and the U.S. English culture.
            /// </param>
            public DefaultValueAttribute(Type type, string value) : base(value) { }
        }
    }
  2. 열 주석에 기본값을 삽입하는 규칙을 만듭니다. 열 주석은
    열에 대한 사용자 지정 메타 데이터를 마이그레이션 스크립트 생성기로 전달하는 데 사용됩니다.
    이를 위해 규칙을 사용하면 각 필드에 대해 개별적으로 지정하지 않고 여러 속성에 대해 유창한 메타 데이터를 정의하고 조작 할 수있는 방법을 단순화하는 속성 표기법의 힘을 보여줍니다.

    namespace EFExtensions
    {
    
        /// <summary>
        /// Implement SQL Default Values from System.ComponentModel.DefaultValueAttribute
        /// </summary>
        public class DefaultValueConvention : Convention
        {
            /// <summary>
            /// Annotation Key to use for Default Values specified directly as an object
            /// </summary>
            public const string DirectValueAnnotationKey = "DefaultValue";
            /// <summary>
            /// Annotation Key to use for Default Values specified as SQL Strings
            /// </summary>
            public const string SqlValueAnnotationKey = "DefaultSql";
    
            /// <summary>
            /// Implement SQL Default Values from System.ComponentModel.DefaultValueAttribute
            /// </summary>
            public DefaultValueConvention()
            {
                // Implement SO Default Value Attributes first
                this.Properties()
                        .Where(x => x.HasAttribute<EFExtensions.DefaultValueAttribute>())
                        .Configure(c => c.HasColumnAnnotation(
                            c.GetAttribute<EFExtensions.DefaultValueAttribute>().GetDefaultValueAttributeKey(),
                            c.GetAttribute<EFExtensions.DefaultValueAttribute>().GetDefaultValueAttributeValue()
                            ));
    
                // Implement Component Model Default Value Attributes, but only if it is not the SO implementation
                this.Properties()
                        .Where(x => x.HasAttribute<System.ComponentModel.DefaultValueAttribute>())
                        .Where(x => !x.HasAttribute<MiniTuber.DataAnnotations.DefaultValueAttribute>())
                        .Configure(c => c.HasColumnAnnotation(
                            DefaultValueConvention.DirectValueAnnotationKey, 
                            c.GetAttribute<System.ComponentModel.DefaultValueAttribute>().Value
                            ));
            }
        }
    
        /// <summary>
        /// Extension Methods to simplify the logic for building column annotations for Default Value processing
        /// </summary>
        public static partial class PropertyInfoAttributeExtensions
        {
            /// <summary>
            /// Wrapper to simplify the lookup for a specific attribute on a property info.
            /// </summary>
            /// <typeparam name="T">Type of attribute to lookup</typeparam>
            /// <param name="self">PropertyInfo to inspect</param>
            /// <returns>True if an attribute of the requested type exists</returns>
            public static bool HasAttribute<T>(this PropertyInfo self) where T : Attribute
            {
                return self.GetCustomAttributes(false).OfType<T>().Any();
            }
    
            /// <summary>
            /// Wrapper to return the first attribute of the specified type
            /// </summary>
            /// <typeparam name="T">Type of attribute to return</typeparam>
            /// <param name="self">PropertyInfo to inspect</param>
            /// <returns>First attribuite that matches the requested type</returns>
            public static T GetAttribute<T>(this System.Data.Entity.ModelConfiguration.Configuration.ConventionPrimitivePropertyConfiguration self) where T : Attribute
            {
                return self.ClrPropertyInfo.GetCustomAttributes(false).OfType<T>().First();
            }
    
            /// <summary>
            /// Helper to select the correct DefaultValue annotation key based on the attribute values
            /// </summary>
            /// <param name="self"></param>
            /// <returns></returns>
            public static string GetDefaultValueAttributeKey(this EFExtensions.DefaultValueAttribute self)
            {
                return String.IsNullOrWhiteSpace(self.DefaultSql) ? DefaultValueConvention.DirectValueAnnotationKey : DefaultValueConvention.SqlValueAnnotationKey;
            }
    
            /// <summary>
            /// Helper to select the correct attribute property to send as a DefaultValue annotation value
            /// </summary>
            /// <param name="self"></param>
            /// <returns></returns>
            public static object GetDefaultValueAttributeValue(this EFExtensions.DefaultValueAttribute self)
            {
                return String.IsNullOrWhiteSpace(self.DefaultSql) ? self.Value : self.DefaultSql;
            }
        }
    
    }
  3. DbContext에 규칙 추가
    이를 달성하는 방법은 여러 가지가 있습니다. ModelCreation 논리의 첫 번째 사용자 지정 단계로 규칙을 선언하고 싶습니다. 이것은 DbContext 클래스에 있습니다.

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        // Use our new DefaultValueConvention
        modelBuilder.Conventions.Add<EFExtensions.DefaultValueConvention>();
    
        // My personal favourites ;)
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    
    }
  4. MigrationCodeGenerator 재정의
    이제 이러한 주석이 모델 내의 열 정의에 적용되었으므로 해당 주석을 사용하도록 마이그레이션 스크립트 생성기를 수정해야합니다. 이를 위해 System.Data.Entity.Migrations.Design.CSharpMigrationCodeGenerator최소한의 변경 만 주입하면되므로 에서 상속합니다 .
    사용자 지정 주석을 처리 한 후에는 최종 출력으로 직렬화되지 않도록 열 정의에서 제거해야합니다.

    다른 사용법을 알아 보려면 기본 클래스 코드를 참조하십시오. http://entityframework.codeplex.com/sourcecontrol/latest#src/EntityFramework/Migrations/Design/CSharpMigrationCodeGenerator.cs

    namespace EFExtensions
    {
        /// <summary>
        /// Implement DefaultValue constraint definition in Migration Scripts.
        /// </summary>
        /// <remarks>
        /// Original guide that provided inspiration for this https://romiller.com/2012/11/30/code-first-migrations-customizing-scaffolded-code/
        /// </remarks>
        public class CustomCodeGenerator : System.Data.Entity.Migrations.Design.CSharpMigrationCodeGenerator
        {
            /// <summary>
            /// Inject Default values from the DefaultValue attribute, if the DefaultValueConvention has been enabled.
            /// </summary>
            /// <seealso cref="DefaultValueConvention"/>
            /// <param name="column"></param>
            /// <param name="writer"></param>
            /// <param name="emitName"></param>
            protected override void Generate(ColumnModel column, IndentedTextWriter writer, bool emitName = false)
            {
                var annotations = column.Annotations?.ToList();
                if (annotations != null && annotations.Any())
                {
                    for (int index = 0; index < annotations.Count; index ++)
                    {
                        var annotation = annotations[index];
                        bool handled = true;
    
                        try
                        {
                            switch (annotation.Key)
                            {
                                case DefaultValueConvention.SqlValueAnnotationKey:
                                    if (annotation.Value?.NewValue != null)
                                    {
                                        column.DefaultValueSql = $"{annotation.Value.NewValue}";
                                    }
                                    break;
                                case DefaultValueConvention.DirectValueAnnotationKey:
                                    if (annotation.Value?.NewValue != null)
                                    {
                                        column.DefaultValue = Convert.ChangeType(annotation.Value.NewValue, column.ClrType);
                                    }
                                    break;
                                default:
                                    handled = false;
                                    break;
                            }
                        }
                        catch(Exception ex)
                        {
                            // re-throw with specific debug information
                            throw new ApplicationException($"Failed to Implement Column Annotation for column: {column.Name} with key: {annotation.Key} and new value: {annotation.Value.NewValue}", ex);
                        }
    
                        if(handled)
                        {
                            // remove the annotation, it has been applied
                            column.Annotations.Remove(annotation.Key);
                        }
                    }
                }
                base.Generate(column, writer, emitName);
            }
    
            /// <summary>
            /// Generates class summary comments and default attributes
            /// </summary>
            /// <param name="writer"> Text writer to add the generated code to. </param>
            /// <param name="designer"> A value indicating if this class is being generated for a code-behind file. </param>
            protected override void WriteClassAttributes(IndentedTextWriter writer, bool designer)
            {
                writer.WriteLine("/// <summary>");
                writer.WriteLine("/// Definition of the Migration: {0}", this.ClassName);
                writer.WriteLine("/// </summary>");
                writer.WriteLine("/// <remarks>");
                writer.WriteLine("/// Generated Time: {0}", DateTime.Now);
                writer.WriteLine("/// Generated By: {0}", Environment.UserName);
                writer.WriteLine("/// </remarks>");
                base.WriteClassAttributes(writer, designer);
            }
    
    
        }
    }
  5. CustomCodeGenerator 등록
    마지막 단계, DbMigration 구성 파일에서 사용할 코드 생성기를 지정해야합니다. 기본적으로 마이그레이션 폴더에서 Configuration.cs를 찾습니다.

    internal sealed class Configuration : DbMigrationsConfiguration<YourApplication.Database.Context>
    {
        public Configuration()
        {
            // I recommend that auto-migrations be disabled so that we control
            // the migrations explicitly 
            AutomaticMigrationsEnabled = false;
            CodeGenerator = new EFExtensions.CustomCodeGenerator();
        }
    
        protected override void Seed(YourApplication.Database.Context context)
        {
            //   Your custom seed logic here
        }
    }

0

어떤 이유로 승인 된 답변이 더 이상 저에게 효과가 없다고 스스로 설명 할 수 없었습니다.

다른 앱에서 작동했지만 내가 작업중인 앱에서는 작동하지 않았습니다.

따라서 대안이지만 매우 비효율적 인 해결책은 아래와 같이 SaveChanges () 메서드를 재정의하는 것입니다. 이 메서드는 Context 클래스에 있어야합니다.

    public override int SaveChanges()
    {
        foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("ColumnName") != null))
        {
            if (entry.State == EntityState.Added)
            {
                entry.Property("ColumnName").CurrentValue = "DefaultValue";
            }
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.