[英]EF 7 set initial default value for DateTime column
我需要能夠設置 DateTime 列的初始值。
當我指定“getutcdate() 或 DateTime.UtcNow
entity.Property(e => e.ShipDate).DefaultValue("getutcdate()")
entity.Property(e => e.ShipDate).DefaultValue(DateTime.UtcNow)
然后運行dnx . ef migration add InitialMigration
dnx . ef migration add InitialMigration
EF 使用以下命令生成遷移快照:
b.Property<DateTime?>("ShipDate")
.Required()
.Annotation("Relational:ColumnDefaultValue", "getutcdate()")
.Annotation("Relational:ColumnDefaultValueType", "System.String");
當我使用 DateTime.UtcNow 時...
b.Property<DateTime?>("ShipDate")
.Annotation("Relational:ColumnDefaultValue", "635754129448768827")
.Annotation("Relational:ColumnDefaultValueType", "System.DateTime");
和初始遷移:
ShipDate = table.Column(
type: "datetime2",
nullable: false,
defaultValue: "getutcdate()"),
當我使用 DateTime.UtcNow 時...
ShipDate = table.Column(
type: "datetime2",
nullable: true,
defaultValue: new DateTime(2015, 8, 17, 12, 55, 44, 876, DateTimeKind.Unspecified)),
看起來它必須工作,但是當我將數據插入表中時,該列的默認值是創建時間戳的“時刻”。
我錯過了什么嗎?
另外,同樣,如何在 EF7 中指定 IDENTITY SEED?
謝謝
更新生成 sql 腳本后,我得到兩個選項:
如果使用“getutcdate()”:
[ShipDate] datetime2 DEFAULT 'getutcdate()',
由於引號而不起作用
或者如果使用 DateTime.utcNow:
[ShipDate] datetime2 DEFAULT '2015-08-17 12:55:44.8760000'
這解釋了我得到的靜態值。
我想我可以應付這個。 這是一個錯誤還是有正確的方法來做到這一點? 謝謝
你想設置默認值 SQL,而不是一個常量值:
entity.Property(e => e.ShipDate).HasDefaultValueSql("getutcdate()");
使用 EF Core 屬性的更靈活的解決方案:
在您的 DbContext 中:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Add your customizations after calling base.OnModelCreating(builder);
CustomDataTypeAttributeConvention.Apply(builder);
DecimalPrecisionAttributeConvention.Apply(builder);
SqlDefaultValueAttributeConvention.Apply(builder);
}
並創建這些類:
public static class SqlDefaultValueAttributeConvention
{
public static void Apply(ModelBuilder builder)
{
ConventionBehaviors
.SetSqlValueForPropertiesWithAttribute<SqlDefaultValueAttribute>(builder, x => x.DefaultValue);
}
}
public static class DecimalPrecisionAttributeConvention
{
public static void Apply(ModelBuilder builder)
{
ConventionBehaviors
.SetTypeForPropertiesWithAttribute<DecimalPrecisionAttribute>(builder,
x => $"decimal({x.Precision}, {x.Scale})");
}
}
public class CustomDataTypeAttributeConvention
{
public static void Apply(ModelBuilder builder)
{
ConventionBehaviors
.SetTypeForPropertiesWithAttribute<DataTypeAttribute>(builder,
x => x.CustomDataType);
}
}
public static class ConventionBehaviors
{
public static void SetTypeForPropertiesWithAttribute<TAttribute>(ModelBuilder builder, Func<TAttribute, string> lambda) where TAttribute : class
{
SetPropertyValue<TAttribute>(builder).ForEach((x) => {
x.Item1.Relational().ColumnType = lambda(x.Item2);
});
}
public static void SetSqlValueForPropertiesWithAttribute<TAttribute>(ModelBuilder builder, Func<TAttribute, string> lambda) where TAttribute : class
{
SetPropertyValue<TAttribute>(builder).ForEach((x) =>
{
x.Item1.Relational().DefaultValueSql = lambda(x.Item2);
});
}
private static List<Tuple<IMutableProperty, TAttribute>> SetPropertyValue<TAttribute>(ModelBuilder builder) where TAttribute : class
{
var propsToModify = new List<Tuple<IMutableProperty, TAttribute>>();
foreach (var entity in builder.Model.GetEntityTypes())
{
var properties = entity.GetProperties();
foreach (var property in properties)
{
var attribute = property.PropertyInfo
.GetCustomAttributes(typeof(TAttribute), false)
.FirstOrDefault() as TAttribute;
if (attribute != null)
{
propsToModify.Add(new Tuple<IMutableProperty, TAttribute>(property, attribute));
}
}
}
return propsToModify;
}
}
和自定義屬性:
/// <summary>
/// Set a default value defined on the sql server
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class SqlDefaultValueAttribute : Attribute
{
/// <summary>
/// Default value to apply
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Set a default value defined on the sql server
/// </summary>
/// <param name="value">Default value to apply</param>
public SqlDefaultValueAttribute(string value)
{
DefaultValue = value;
}
}
/// <summary>
/// Set the decimal precision of a decimal sql data type
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class DecimalPrecisionAttribute : Attribute
{
/// <summary>
/// Specify the precision - the number of digits both left and right of the decimal
/// </summary>
public int Precision { get; set; }
/// <summary>
/// Specify the scale - the number of digits to the right of the decimal
/// </summary>
public int Scale { get; set; }
/// <summary>
/// Set the decimal precision of a decimal sql data type
/// </summary>
/// <param name="precision">Specify the precision - the number of digits both left and right of the decimal</param>
/// <param name="scale">Specify the scale - the number of digits to the right of the decimal</param>
public DecimalPrecisionAttribute(int precision, int scale)
{
Precision = precision;
Scale = scale;
}
public DecimalPrecisionAttribute(int[] values)
{
Precision = values[0];
Scale = values[1];
}
}
然后,您將能夠使用這些屬性中的任何一個來裝飾您的表屬性(或制作您自己的自定義屬性):
[DecimalPrecision(18, 9)]
[SqlDefaultValue("getutcdate()")]
[DataType("decimal(18,9)")]
@Michael Brown感謝您提供這些自定義屬性,
更新(EF Core 3.x):從 EF Core 3.0 開始,元數據 API 再次發生變化 -
Relational()
擴展已被刪除,屬性已被替換為Get
和Set
擴展方法,因此現在代碼如下所示:在此答案中感謝@Ivan Stoev https://stackoverflow.com/a/42467710/1475257
所以來自@Michael Brown在NET Core和.NET 5 中的整個代碼將是
public static class DecimalPrecisionAttributeConvention
{
public static void Apply(ModelBuilder builder)
{
ConventionBehaviors
.SetTypeForPropertiesWithAttribute<DecimalPrecisionAttribute>(builder,
x => $"decimal({x.Precision}, {x.Scale})");
}
}
public class CustomDataTypeAttributeConvention
{
public static void Apply(ModelBuilder builder)
{
ConventionBehaviors
.SetTypeForPropertiesWithAttribute<DataTypeAttribute>(builder,
x => x.CustomDataType);
}
}
public static class ConventionBehaviors
{
public static void SetTypeForPropertiesWithAttribute<TAttribute>(ModelBuilder builder, Func<TAttribute, string> lambda) where TAttribute : class
{
SetPropertyValue<TAttribute>(builder).ForEach((x) =>
{
x.Item1.SetColumnType(lambda(x.Item2));
});
}
public static void SetSqlValueForPropertiesWithAttribute<TAttribute>(ModelBuilder builder, Func<TAttribute, string> lambda) where TAttribute : class
{
SetPropertyValue<TAttribute>(builder).ForEach((x) =>
{
x.Item1.SetDefaultValueSql(lambda(x.Item2));
});
}
private static List<Tuple<IMutableProperty, TAttribute>> SetPropertyValue<TAttribute>(ModelBuilder builder) where TAttribute : class
{
var propsToModify = new List<Tuple<IMutableProperty, TAttribute>>();
foreach (var entity in builder.Model.GetEntityTypes())
{
var properties = entity.GetProperties();
foreach (var property in properties)
{
var attribute = property.PropertyInfo
.GetCustomAttributes(typeof(TAttribute), false)
.FirstOrDefault() as TAttribute;
if (attribute != null)
{
propsToModify.Add(new Tuple<IMutableProperty, TAttribute>(property, attribute));
}
}
}
return propsToModify;
}
}
/// <summary>
/// Set a default value defined on the sql server
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class SqlDefaultValueAttribute : Attribute
{
/// <summary>
/// Default value to apply
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Set a default value defined on the sql server
/// </summary>
/// <param name="value">Default value to apply</param>
public SqlDefaultValueAttribute(string value)
{
DefaultValue = value;
}
}
/// <summary>
/// Set the decimal precision of a decimal sql data type
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class DecimalPrecisionAttribute : Attribute
{
/// <summary>
/// Specify the precision - the number of digits both left and right of the decimal
/// </summary>
public int Precision { get; set; }
/// <summary>
/// Specify the scale - the number of digits to the right of the decimal
/// </summary>
public int Scale { get; set; }
/// <summary>
/// Set the decimal precision of a decimal sql data type
/// </summary>
/// <param name="precision">Specify the precision - the number of digits both left and right of the decimal</param>
/// <param name="scale">Specify the scale - the number of digits to the right of the decimal</param>
public DecimalPrecisionAttribute(int precision, int scale)
{
Precision = precision;
Scale = scale;
}
public DecimalPrecisionAttribute(int[] values)
{
Precision = values[0];
Scale = values[1];
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.