在 System.ComponentModel 默认值属性中将 DateTime 属性的默认值设置为 DateTime.Now
Posted
技术标签:
【中文标题】在 System.ComponentModel 默认值属性中将 DateTime 属性的默认值设置为 DateTime.Now【英文标题】:Setting the default value of a DateTime Property to DateTime.Now inside the System.ComponentModel Default Value Attrbute 【发布时间】:2010-10-16 00:24:46 【问题描述】:有人知道如何使用 System.ComponentModel DefaultValue 属性为 DateTime 属性指定默认值吗?
例如我试试这个:
[DefaultValue(typeof(DateTime),DateTime.Now.ToString("yyyy-MM-dd"))]
public DateTime DateCreated get; set;
并且它期望值是一个常量表达式。
这是在使用 ASP.NET 动态数据的上下文中。我不想搭建 DateCreated 列,而只是提供 DateTime.Now(如果它不存在)。我使用实体框架作为我的数据层
干杯,
安德鲁
【问题讨论】:
【参考方案1】:您不能对属性执行此操作,因为它们只是在编译时生成的元信息。如果需要,只需将代码添加到构造函数以初始化日期,创建触发器并处理数据库中的缺失值,或者以返回 DateTime.Now 的方式实现 getter(如果支持字段未初始化)。
public DateTime DateCreated
get
return this.dateCreated.HasValue
? this.dateCreated.Value
: DateTime.Now;
set this.dateCreated = value;
private DateTime? dateCreated = null;
【讨论】:
谢谢,在你编辑之前,我走另一条路,拦截了二传手。为帮助干杯:-) Aget
部分可以简化为:return dateCreated ?? DateTime.Now;
如果您希望您的课程作为 POCO,此解决方案可能会出现问题。就我而言,我的课程应该与通过 WCF 传输的 POCO 课程一样清晰。
@zHs 这对我使用 Database First 和 Entity Framework 非常有用。
如果您来这里获取属性,请查看this answer。【参考方案2】:
在 DateTime 属性中添加以下内容
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
【讨论】:
这实际上是我一直在寻找的,它应该会变得更高。许多其他答案确实在插入实体时添加了当前日期,但它不会影响架构(即,将 getdate() 设为默认值)。对我来说,问题是当我想将记录直接添加到表中(使用 SQL)时,我必须提供日期(或将其保留为 NULL)。这是一个更好的解决方案。谢谢。 .Computed 用于添加和更新操作。仅将 .Identity 用于添加。 迄今为止的最佳答案:应该添加对 System.ComponentModel.DataAnnotations.Schema 的引用应该为 DatabaseGenerated 注释添加 将使用哪个时区?会是 UTC 吗? 将 ASP.NET Core 3.1 与 codefirst 迁移一起使用,不幸的是,这没有任何作用 :( 我赞成,因为这是一个很好的答案,但不适用于我的情况【参考方案3】:我已经在 EF core 2.1
上对此进行了测试在这里您不能使用约定或数据注释。您必须使用 Fluent API。
class MyContext : DbContext
public DbSet<Blog> Blogs get; set;
protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<Blog>()
.Property(b => b.Created)
.HasDefaultValueSql("getdate()");
Official doc
【讨论】:
这正是我想要的,但是由于我的属性在 BaseClass 上,所以我不能(它为 BaseClass 创建了一个新表)。然而,检查 ChangeTracker using this link 解决了它(设置 Created 和 Updated 时间戳)。【参考方案4】:我没有理由想出它不应该通过属性来完成。它可能在微软的积压中。谁知道呢。
我找到的最佳解决方案是在代码先迁移中使用 defaultValueSql 参数。
CreateTable(
"dbo.SomeTable",
c => new
TheDateField = c.DateTime(defaultValueSql: "GETDATE()")
);
我不喜欢在实体类构造函数中设置它的常用参考解决方案,因为如果实体框架以外的任何东西在该表中粘贴记录,日期字段将不会获得默认值。使用触发器来处理这种情况的想法对我来说似乎是错误的。
【讨论】:
在更改和添加可为空的情况下使用 AddColumn("dbo.table", "Created", c => c.DateTime( nullable:true, defaultValueSql:"getdate()" ) ); 这不是个好主意,如果你会选择你的数据库,你需要重构这段代码。 最好同时使用构造函数和 defaultValueSql,这样你的类在有和没有 EF 的情况下都可以工作吗?【参考方案5】:这是可能的,而且非常简单:
为DateTime.MinValue
[System.ComponentModel.DefaultValue(typeof(DateTime), "")]
对于作为DefaultValueAttribute
的最后一个参数的任何其他值,指定表示所需日期时间值的字符串。
此值必须是常量表达式,并且是使用 TypeConverter
创建对象 (DateTime
) 所必需的。
【讨论】:
我愿意相信这种用法对我有用,但不幸的是它没有。迁移结果;defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)
刚刚尝试输入一个字符串日期(“1/1/20”)而不是空字符串,它转换成功。
嗯,当然,但是......实际的问题是将其设置为当前日期时间。哪一个,afaik,必须在 Fluent API(我讨厌)或数据库中完成。【参考方案6】:
刚刚发现这个正在寻找不同的东西,但在新的 C# 版本中,您可以使用更短的版本:
public DateTime DateCreated get; set; = DateTime.Now;
【讨论】:
很棒的答案,正是我想要的 这个总是可以安全使用吗? 想不出有什么缺点,官方文档很少提到自动初始化docs.microsoft.com/en-us/dotnet/csharp/programming-guide/… 是否可以添加日期格式?比如:DateTime.Now.ToString("yyyyMMddhh") 如果你想要一个字符串属性而不是 DateTime,那么是的,你可以将你的代码添加到初始化程序中。【参考方案7】:如果您使用实体框架,一个简单的解决方案是添加一个部分类并为实体定义一个构造函数,因为框架没有定义一个。例如,如果您有一个名为 Example 的实体,您可以将以下代码放在单独的文件中。
namespace EntityExample
public partial class Example : EntityObject
public Example()
// Initialize certain default values here.
this._DateCreated = DateTime.Now;
【讨论】:
这是迄今为止最优雅(也可能也是预期的)问题的解决方案。但这是假设人们使用的是 EF Code First。 我就是这样做的,直到我意识到向我的实体添加一个复杂的属性会导致 EF 生成一个默认构造函数,让我无法编写自己的...【参考方案8】:我认为最简单的解决方案是设置
Created DATETIME2 NOT NULL DEFAULT GETDATE()
在列声明和 VS2010 EntityModel 设计器中设置对应的列属性StoreGeneratedPattern = Computed。
【讨论】:
如果我这样做并使属性可以为空,我会收到 EDMX 验证错误,因为不可为空的列映射到可空的属性。 如果您使用的是 EDMX,那么您没有使用 EF Core【参考方案9】:创建一个新的属性类是一个很好的建议。在我的例子中,我想指定 'default(DateTime)' 或 'DateTime.MinValue' 以便 Newtonsoft.Json 序列化程序会忽略没有实际值的 DateTime 成员。
[JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore )]
[DefaultDateTime]
public DateTime EndTime;
public class DefaultDateTimeAttribute : DefaultValueAttribute
public DefaultDateTimeAttribute()
: base( default( DateTime ) )
public DefaultDateTimeAttribute( string dateTime )
: base( DateTime.Parse( dateTime ) )
如果没有 DefaultValue 属性,即使设置了 DefaultValueHandling.Ignore 选项,JSON 序列化程序也会输出“1/1/0001 12:00:00 AM”。
【讨论】:
【参考方案10】:只需考虑在实体类的构造函数中设置其值
public class Foo
public DateTime DateCreated get; set;
public Foo()
DateCreated = DateTime.Now;
【讨论】:
这对我有用。尽管在执行此操作之前我必须将Datetime
属性设置为空。【参考方案11】:
使用 System.ComponentModel.DataAnnotations.Schema;
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedOn get; private set;
【讨论】:
请查看how to answer【参考方案12】:我需要一个 UTC 时间戳作为默认值,因此修改了 Daniel 的解决方案,如下所示:
[Column(TypeName = "datetime2")]
[XmlAttribute]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "0:yyyy-MM-dd")]
[Display(Name = "Date Modified")]
[DateRange(Min = "1900-01-01", Max = "2999-12-31")]
public DateTime DateModified
get return dateModified;
set dateModified = value;
private DateTime dateModified = DateTime.Now.ToUniversalTime();
DateRangeAttribute 教程见this awesome blog post
【讨论】:
【参考方案13】:有办法。添加这些类:
DefaultDateTimeValueAttribute.cs
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Custom.Extensions;
namespace Custom.DefaultValueAttributes
/// <summary>
/// This class's DefaultValue attribute allows the programmer to use DateTime.Now as a default value for a property.
/// Inspired from https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class DefaultDateTimeValueAttribute : DefaultValueAttribute
public string DefaultValue get; set;
private object _value;
public override object Value
get
if (_value == null)
return _value = GetDefaultValue();
return _value;
/// <summary>
/// Initialized a new instance of this class using the desired DateTime value. A string is expected, because the value must be generated at runtime.
/// Example of value to pass: Now. This will return the current date and time as a default value.
/// Programmer tip: Even if the parameter is passed to the base class, it is not used at all. The property Value is overridden.
/// </summary>
/// <param name="defaultValue">Default value to render from an instance of <see cref="DateTime"/></param>
public DefaultDateTimeValueAttribute(string defaultValue) : base(defaultValue)
DefaultValue = defaultValue;
public static DateTime GetDefaultValue(Type objectType, string propertyName)
var property = objectType.GetProperty(propertyName);
var attribute = property.GetCustomAttributes(typeof(DefaultDateTimeValueAttribute), false)
?.Cast<DefaultDateTimeValueAttribute>()
?.FirstOrDefault();
return attribute.GetDefaultValue();
private DateTime GetDefaultValue()
// Resolve a named property of DateTime, like "Now"
if (this.IsProperty)
return GetPropertyValue();
// Resolve a named extension method of DateTime, like "LastOfMonth"
if (this.IsExtensionMethod)
return GetExtensionMethodValue();
// Parse a relative date
if (this.IsRelativeValue)
return GetRelativeValue();
// Parse an absolute date
return GetAbsoluteValue();
private bool IsProperty
=> typeof(DateTime).GetProperties()
.Select(p => p.Name).Contains(this.DefaultValue);
private bool IsExtensionMethod
=> typeof(DefaultDateTimeValueAttribute).Assembly
.GetType(typeof(DefaultDateTimeExtensions).FullName)
.GetMethods()
.Where(m => m.IsDefined(typeof(ExtensionAttribute), false))
.Select(p => p.Name).Contains(this.DefaultValue);
private bool IsRelativeValue
=> this.DefaultValue.Contains(":");
private DateTime GetPropertyValue()
var instance = Activator.CreateInstance<DateTime>();
var value = (DateTime)instance.GetType()
.GetProperty(this.DefaultValue)
.GetValue(instance);
return value;
private DateTime GetExtensionMethodValue()
var instance = Activator.CreateInstance<DateTime>();
var value = (DateTime)typeof(DefaultDateTimeValueAttribute).Assembly
.GetType(typeof(DefaultDateTimeExtensions).FullName)
.GetMethod(this.DefaultValue)
.Invoke(instance, new object[] DateTime.Now );
return value;
private DateTime GetRelativeValue()
TimeSpan timeSpan;
if (!TimeSpan.TryParse(this.DefaultValue, out timeSpan))
return default(DateTime);
return DateTime.Now.Add(timeSpan);
private DateTime GetAbsoluteValue()
DateTime value;
if (!DateTime.TryParse(this.DefaultValue, out value))
return default(DateTime);
return value;
DefaultDateTimeExtensions.cs
using System;
namespace Custom.Extensions
/// <summary>
/// Inspired from https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19. See usage for more information.
/// </summary>
public static class DefaultDateTimeExtensions
public static DateTime FirstOfYear(this DateTime dateTime)
=> new DateTime(dateTime.Year, 1, 1, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
public static DateTime LastOfYear(this DateTime dateTime)
=> new DateTime(dateTime.Year, 12, 31, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
public static DateTime FirstOfMonth(this DateTime dateTime)
=> new DateTime(dateTime.Year, dateTime.Month, 1, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
public static DateTime LastOfMonth(this DateTime dateTime)
=> new DateTime(dateTime.Year, dateTime.Month, DateTime.DaysInMonth(dateTime.Year, dateTime.Month), dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
并使用 DefaultDateTimeValue 作为属性的属性。输入到您的验证属性的值类似于“Now”,它将在运行时从使用 Activator 创建的 DateTime 实例呈现。源代码的灵感来自这个线程:https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19。我对其进行了更改,以使我的类使用 DefaultValueAttribute 而不是 ValidationAttribute 继承。
【讨论】:
【参考方案14】:我遇到了同样的问题,但最适合我的问题如下:
public DateTime CreatedOn get; set; = DateTime.Now;
【讨论】:
【参考方案15】:在 C# 版本 6 中,可以提供默认值
public DateTime fieldname get; set; = DateTime.Now;
【讨论】:
欢迎使用 ***:如果您发布代码、XML 或数据示例,请在文本编辑器中突出显示这些行,然后单击编辑器工具栏上的“代码示例”按钮 ( ) 或使用 Ctrl键盘上的 +K 可以很好地格式化和语法突出显示它! 同Brandtware的回答***.com/a/47528230/52277【参考方案16】:使用EntityTypeConfiguration
,我得到这样的结果:
public class UserMap : IEntityTypeConfiguration<User>
public void Configure(EntityTypeBuilder<User> builder)
//throw new NotImplementedException();
builder.Property(u => u.Id).ValueGeneratedOnAdd();
builder.Property(u => u.Name).IsRequired().HasMaxLength(100);
builder.HasIndex(u => u.Email).IsUnique();
builder.Property(u => u.Status).IsRequired();
builder.Property(u => u.Password).IsRequired();
builder.Property(u => u.Registration).HasDefaultValueSql("getdate()");
builder.HasMany(u => u.DrawUser).WithOne(u => u.User);
builder.ToTable("User");
【讨论】:
【参考方案17】:public DateTime DateCreated
get
return (this.dateCreated == default(DateTime))
? this.dateCreated = DateTime.Now
: this.dateCreated;
set this.dateCreated = value;
private DateTime dateCreated = default(DateTime);
【讨论】:
【参考方案18】:您目前如何处理这取决于您使用的是什么模型 Linq to SQL 或 EntityFramework?
在L2S中你可以添加
public partial class NWDataContext
partial void InsertCategory(Category instance)
if(Instance.Date == null)
Instance.Data = DateTime.Now;
ExecuteDynamicInsert(instance);
EF 稍微复杂一点,请参阅http://msdn.microsoft.com/en-us/library/cc716714.aspx 了解有关 EF 业务逻辑的更多信息。
【讨论】:
【参考方案19】:我知道这篇文章有点老了,但是有一个建议可以帮助一些人。
我使用 Enum 来确定要在属性构造函数中设置什么。
财产声明:
[DbProperty(initialValue: EInitialValue.DateTime_Now)]
public DateTime CreationDate get; set;
属性构造函数:
Public Class DbProperty Inherits System.Attribute
Public Property InitialValue As Object
Public Sub New(ByVal initialValue As EInitialValue)
Select Case initialValue
Case EInitialValue.DateTime_Now
Me.InitialValue = System.DateTime.Now
Case EInitialValue.DateTime_Min
Me.InitialValue = System.DateTime.MinValue
Case EInitialValue.DateTime_Max
Me.InitialValue = System.DateTime.MaxValue
End Select
End Sub
End Class
枚举:
Public Enum EInitialValue
DateTime_Now
DateTime_Min
DateTime_Max
End Enum
【讨论】:
【参考方案20】:我认为您可以使用StoreGeneratedPattern = Identity
(在模型设计器属性窗口中设置)来做到这一点。
我没想到会是这样,但在试图弄清楚时,我注意到我的一些日期列已经默认为CURRENT_TIMESTAMP()
,而有些则不是。检查模型,我发现除了名称之外,两列之间的唯一区别是获得默认值的那一列将StoreGeneratedPattern
设置为Identity
。
我没想到会这样,但是阅读说明,这有点道理:
确定数据库中的相应列是否会在插入和更新操作期间自动生成。
此外,虽然这确实使数据库列具有“现在”的默认值,但我想它实际上并没有在 POCO 中将属性设置为DateTime.Now
。这对我来说不是问题,因为我有一个自定义的 .tt 文件,它已经自动将我的所有日期列设置为 DateTime.Now
(实际上自己修改 .tt 文件并不难,特别是如果你有 ReSharper 并获得一个语法高亮插件。(新版本的 VS 可能已经语法高亮 .tt 文件,不确定。))
对我来说,问题是:如何让数据库列具有默认值,以便省略该列的现有查询仍然有效?上面的设置适用于此。
我尚未对其进行测试,但设置它也可能会干扰设置您自己的显式值。 (我最初只是偶然发现了这一点,因为 EF6 Database First 以这种方式为我编写了模型。)
【讨论】:
【参考方案21】:以下适用于 .NET 5.0
private DateTime _DateCreated= DateTime.Now;
public DateTime DateCreated
get
return this._DateCreated;
set this._DateCreated = value;
【讨论】:
【参考方案22】:您也可以考虑使用 DatabaseGenerated 属性,例如
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime DateCreated get; set;
https://docs.microsoft.com/en-us/ef/core/modeling/generated-properties?tabs=data-annotations
【讨论】:
【参考方案23】:使用 Fluent API,在 Context 类的 OnModelCreating 函数中添加以下内容。
builder.Property(u => u.CreatedAt).ValueGeneratedOnAdd();
builder.Property(u => u.UpdatedAt).ValueGeneratedOnAddOrUpdate();
注意我正在使用一个单独的类型配置类。如果你在函数中做得对,就像:
builder.Enitity<User>().Property(u => u.CreatedAt).ValueGeneratedOnAdd();
【讨论】:
【参考方案24】:我也想要这个并想出了这个解决方案(我只使用日期部分 - 默认时间作为 PropertyGrid 默认值没有意义):
public class DefaultDateAttribute : DefaultValueAttribute
public DefaultDateAttribute(short yearoffset)
: base(DateTime.Now.AddYears(yearoffset).Date)
这只会创建一个新属性,您可以将其添加到 DateTime 属性中。 例如。如果它默认为 DateTime.Now.Date:
[DefaultDate(0)]
【讨论】:
警告!!!!!!这非常糟糕,应该从 SO 中删除。我只是花了几个小时调试这个建议引起的问题。乍一看,它看起来不错,而且似乎可以工作。但这是一个陷阱。属性需要静态值是有原因的。它们被初始化一次。之后,值发生变化。因此,虽然您创建的第一个实例看起来不错,后续实例看起来也不错,但它们实际上都使用了第一个值。一旦你的应用程序运行了一段时间,你就会注意到这个问题并想知道为什么。在调试中,当你运行它一分钟时,它会运行良好。当心! 克里斯是对的。我发现了同样的问题。 不要使用这个答案。以上是关于在 System.ComponentModel 默认值属性中将 DateTime 属性的默认值设置为 DateTime.Now的主要内容,如果未能解决你的问题,请参考以下文章
使用 AvalonDock 2.0 时未处理的“System.ComponentModel.Win32Exception”
无法将类型为“System.Windows.Forms.SplitContainer”的对象强制转换为类型“System.ComponentModel.ISupportInitialize”
Azure DevOps Build 出现错误:找不到程序集“System.ComponentModel.Annotations”
无法在设计器中加载文件或程序集 System.Componentmodel.Annotations 4.2.0.0
在 System.ComponentModel 默认值属性中将 DateTime 属性的默认值设置为 DateTime.Now