相当于 modelBuilder 的 HasDefaultValueSql 的 Entity Framework Core 属性是什么?
What is the Entity Framework Core attribute equivalent to modelBuilder's HasDefaultValueSql?
我想使用注释来设置我在 Entity Framework Core 中的属性的默认值。问题是数据库没有设置默认值,因此该值没有传递到数据库层。
我想做类似于 modelBuilder
的 HasDefaultValueSql
:
[DefaultValue("400")]
public int LengthInMeters {get; set;}
如何将以下代码转换为属性?
modelBuilder.Entity<Patient>().Property(c => c.LengthInMeters).HasDefaultValueSql("400");
单独使用默认值是行不通的。我想单独使用属性而不必弄乱迁移。
问题:我尝试过使用 EF 的其他方法,但 Entity Framework Core 没有一些项目。比如modelBuilder.Conventions
也不AttributeToColumnAnnotationConvention
也不CSharpMigrationCodeGenerator
也不modelBuilder.Properties()
,如果有人有更清洁而不是密集的实施方式,请告诉我。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entityType.GetProperties())
{
var memberInfo = property.PropertyInfo ?? (MemberInfo)property.FieldInfo;
if (memberInfo == null) continue;
var defaultValue = Attribute.GetCustomAttribute(memberInfo, typeof(DefaultValueAttribute)) as DefaultValueAttribute;
if (defaultValue == null) continue;
property.SqlServer().DefaultValue = defaultValue.Value;
}
}
}
我可以使用默认值属性在数据库中设置默认值
[DefaultValue("400")]
public int LengthInMeters {get; set;}
使用 EF-Core 约定以另一种方式完成这项工作时遇到了困难。我发现了一种添加所谓的“插件”的方法,它实现了 IConventionSetPlugin
接口,您可以使用该接口添加自定义约定。它需要一些额外的代码才能让 EntityFramework 使用插件。
但首先,让我们创建我们的 PropertyAttributeConvention
。
public class DefaultValueAttributeConvention : PropertyAttributeConventionBase<DefaultValueAttribute>
{
public DefaultValueAttributeConvention(ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { }
protected override void ProcessPropertyAdded(IConventionPropertyBuilder propertyBuilder, DefaultValueAttribute attribute,
MemberInfo clrMember, IConventionContext context)
{
propertyBuilder.HasDefaultValue(attribute.Value, fromDataAnnotation: true);
}
}
这里我们只是说 ef propertybuilder 使用我们 [DefaultValue]
属性中定义的默认值。
要添加约定,我们需要创建一个自定义插件 class:
public class CustomConventionSetPlugin : IConventionSetPlugin
{
public ConventionSet ModifyConventions(ConventionSet conventionSet)
{
conventionSet.PropertyAddedConventions.Add(new DefaultValueAttributeConvention(null));
return conventionSet;
}
}
为了使用我们的插件,我们必须创建一个 ef 扩展 class(它本身包含另一个 ExtensionInfo
class)
public class CustomDbContextOptionsExtension : IDbContextOptionsExtension
{
public void ApplyServices(IServiceCollection services)
{
services.AddSingleton<IConventionSetPlugin, CustomConventionSetPlugin>();
}
public void Validate(IDbContextOptions options) { }
public DbContextOptionsExtensionInfo Info => new CustomDbContextOptionsExtensionInfo(this);
private class CustomDbContextOptionsExtensionInfo : DbContextOptionsExtensionInfo
{
public CustomDbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) : base(extension) { }
public override long GetServiceProviderHashCode() => 0;
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo) { }
public override bool IsDatabaseProvider => false;
public override string LogFragment => "";
}
}
在扩展 class 中,我们将插件 class 添加到 EF-ServiceCollection
。
最后一步是转到我们的 DbContext
并添加我们的扩展程序。这可以在 OnConfigure
方法中完成:
public class MyDatacontext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(new CustomDbContextOptionsExtension());
}
}
现在 [DefaultValue]
属性可以用于我们的实体属性。
如果我们想添加不同的自定义约定,我们不必再次创建所有 extension/plugin classes。只需创建一个新约定 class 并通过我们现有的插件 class 将其添加到 convetionSet
.
安装 Microsoft.EntityFrameworkCore.Relational 包,它应该可以解决迁移到 EF 核心时的大部分迁移问题。
我想使用注释来设置我在 Entity Framework Core 中的属性的默认值。问题是数据库没有设置默认值,因此该值没有传递到数据库层。
我想做类似于 modelBuilder
的 HasDefaultValueSql
:
[DefaultValue("400")]
public int LengthInMeters {get; set;}
如何将以下代码转换为属性?
modelBuilder.Entity<Patient>().Property(c => c.LengthInMeters).HasDefaultValueSql("400");
单独使用默认值是行不通的。我想单独使用属性而不必弄乱迁移。
问题:我尝试过使用 EF 的其他方法,但 Entity Framework Core 没有一些项目。比如modelBuilder.Conventions
也不AttributeToColumnAnnotationConvention
也不CSharpMigrationCodeGenerator
也不modelBuilder.Properties()
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entityType.GetProperties())
{
var memberInfo = property.PropertyInfo ?? (MemberInfo)property.FieldInfo;
if (memberInfo == null) continue;
var defaultValue = Attribute.GetCustomAttribute(memberInfo, typeof(DefaultValueAttribute)) as DefaultValueAttribute;
if (defaultValue == null) continue;
property.SqlServer().DefaultValue = defaultValue.Value;
}
}
}
我可以使用默认值属性在数据库中设置默认值
[DefaultValue("400")]
public int LengthInMeters {get; set;}
使用 EF-Core 约定以另一种方式完成这项工作时遇到了困难。我发现了一种添加所谓的“插件”的方法,它实现了 IConventionSetPlugin
接口,您可以使用该接口添加自定义约定。它需要一些额外的代码才能让 EntityFramework 使用插件。
但首先,让我们创建我们的 PropertyAttributeConvention
。
public class DefaultValueAttributeConvention : PropertyAttributeConventionBase<DefaultValueAttribute>
{
public DefaultValueAttributeConvention(ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { }
protected override void ProcessPropertyAdded(IConventionPropertyBuilder propertyBuilder, DefaultValueAttribute attribute,
MemberInfo clrMember, IConventionContext context)
{
propertyBuilder.HasDefaultValue(attribute.Value, fromDataAnnotation: true);
}
}
这里我们只是说 ef propertybuilder 使用我们 [DefaultValue]
属性中定义的默认值。
要添加约定,我们需要创建一个自定义插件 class:
public class CustomConventionSetPlugin : IConventionSetPlugin
{
public ConventionSet ModifyConventions(ConventionSet conventionSet)
{
conventionSet.PropertyAddedConventions.Add(new DefaultValueAttributeConvention(null));
return conventionSet;
}
}
为了使用我们的插件,我们必须创建一个 ef 扩展 class(它本身包含另一个 ExtensionInfo
class)
public class CustomDbContextOptionsExtension : IDbContextOptionsExtension
{
public void ApplyServices(IServiceCollection services)
{
services.AddSingleton<IConventionSetPlugin, CustomConventionSetPlugin>();
}
public void Validate(IDbContextOptions options) { }
public DbContextOptionsExtensionInfo Info => new CustomDbContextOptionsExtensionInfo(this);
private class CustomDbContextOptionsExtensionInfo : DbContextOptionsExtensionInfo
{
public CustomDbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) : base(extension) { }
public override long GetServiceProviderHashCode() => 0;
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo) { }
public override bool IsDatabaseProvider => false;
public override string LogFragment => "";
}
}
在扩展 class 中,我们将插件 class 添加到 EF-ServiceCollection
。
最后一步是转到我们的 DbContext
并添加我们的扩展程序。这可以在 OnConfigure
方法中完成:
public class MyDatacontext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(new CustomDbContextOptionsExtension());
}
}
现在 [DefaultValue]
属性可以用于我们的实体属性。
如果我们想添加不同的自定义约定,我们不必再次创建所有 extension/plugin classes。只需创建一个新约定 class 并通过我们现有的插件 class 将其添加到 convetionSet
.
安装 Microsoft.EntityFrameworkCore.Relational 包,它应该可以解决迁移到 EF 核心时的大部分迁移问题。