특정 속성에 기본값을 부여하는 “우아한”방법이 있습니까?
아마도 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; }
이 두 기사의 도움을 받았습니다.
제가 한:
속성 정의
[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;
}
}
그런 다음 마이그레이션 구성 생성자에서 사용자 정의 SQL 생성기를 등록하십시오.
SetSqlGenerator("System.Data.SqlClient", new CustomMigrationSqlGenerator());
답변
위의 답변은 실제로 도움이되었지만 솔루션의 일부만 제공했습니다. 가장 큰 문제는 기본값 속성을 제거하자마자 데이터베이스 열의 제약 조건이 제거되지 않는다는 것입니다. 따라서 이전 기본값은 여전히 데이터베이스에 남아 있습니다.
다음은 속성 제거에 대한 SQL 제한 조건 제거를 포함하여 문제점에 대한 완전한 솔루션입니다. 또한 .NET Framework의 기본 DefaultValue
특성을 재사용하고 있습니다.
용법
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[DefaultValue("getutcdate()")]
public DateTime CreatedOn { get; set; }
이것이 작동하려면 IdentityModels.cs 및 Configuration.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 파일
다음 Configuration
과 같이 사용자 지정 SQL 생성기를 등록 하여 클래스 생성자를 업데이트하십시오 .
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; }
}
}
vs.
public class Track
{
public Track()
{
LengthInMeters = 400;
}
public int LengthInMeters { get; set; }
}
이 특정 클래스를 사용하여 데이터를 작성하고 소비하는 응용 프로그램에서만 작동합니다. 데이터 액세스 코드가 중앙 집중화 된 경우 일반적으로 문제가되지 않습니다. 모든 애플리케이션 에서 값을 업데이트하려면 기본값을 설정하도록 데이터 소스를 구성해야합니다. Devi의 답변 은 마이그레이션, SQL 또는 데이터 소스가 사용하는 언어를 사용하여 수행하는 방법을 보여줍니다.
답변
내가 한 일, 엔티티의 생성자에서 값을 초기화했습니다.
참고 : DefaultValue 속성은 속성 값을 자동으로 설정하지 않으므로 직접해야합니다.
답변
@SedatKapanoglu 의견 후에 유창한 API를 사용하면 작동하지 않는 모든 접근 방식을 추가하고 있습니다. 유창한 API를 사용하면 작동하지 않습니다.
1- 사용자 정의 코드 생성기를 작성하고 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- 유창한 API를 사용하여 주석을 작성하십시오.
public static void Configure(DbModelBuilder builder){
builder.Entity<Company>().Property(c => c.Status).HasColumnAnnotation("Default", 0);
}
답변
간단 해! 필수로 주석을 달기 만하면됩니다.
[Required]
public bool MyField { get; set; }
결과 마이그레이션은 다음과 같습니다.
migrationBuilder.AddColumn<bool>(
name: "MyField",
table: "MyTable",
nullable: false,
defaultValue: false);
true를 원하면 데이터베이스를 업데이트하기 전에 마이그레이션에서 defaultValue를 true로 변경하십시오.