将System.ComponentModel默认值Attrbute中的DateTime属性的默认值设置为DateTime.Now
是否有人知道如何使用System.ComponentModel DefaultValue属性指定DateTime属性的Default值?
例如我试试这个:
[DefaultValue(typeof(DateTime),DateTime.Now.ToString("yyyy-MM-dd"))] public DateTime DateCreated { get; set; }
它期望价值是一个不变的expression。
这是与ASP.NETdynamic数据一起使用的上下文。 我不想支架DateCreated列,但只是提供DateTime.Now,如果它不存在。 我正在使用entity framework作为我的数据层
干杯,
安德鲁
你不能用属性来做这件事,因为它们只是编译时生成的元信息。 只要将代码添加到构造函数中以根据需要初始化date,创build触发器并处理数据库中的缺失值,或者以返回DateTime.Now的方式实现getter,前提是未初始化后备字段。
public DateTime DateCreated { get { return this.dateCreated.HasValue ? this.dateCreated.Value : DateTime.Now; } set { this.dateCreated = value; } } private DateTime? dateCreated = null;
我没有理由想出,通过一个属性不应该是可能的。 这可能是在微软的积压。 谁知道。
我发现的最好的解决scheme是在代码第一次迁移中使用defaultValueSql参数。
CreateTable( "dbo.SomeTable", c => new { TheDateField = c.DateTime(defaultValueSql: "GETDATE()") });
我不喜欢在实体类构造函数中设置它的常用引用解决scheme,因为如果Entity Framework以外的任何内容在该表中粘贴logging,则date字段将不会获得默认值。 而使用触发器来处理这种情况的想法对我来说似乎是错误的。
如果您使用entity framework,一个简单的解决scheme是添加一个partical类,并为该实体定义一个构造函数,因为该框架没有定义它。 例如,如果你有一个名为Example的实体,你可以把下面的代码放在一个单独的文件中。
namespace EntityExample { public partial class Example : EntityObject { public Example() { // Initialize certain default values here. this._DateCreated = DateTime.Now; } } }
这是可能的,很简单:
为DateTime.MinValue
[System.ComponentModel.DefaultValue(typeof(DateTime), "")]
作为DefaultValueAttribute
最后一个参数的任何其他值指定表示期望的DateTime值的string。
此值必须是常量expression式,并且需要使用TypeConverter
创build对象( DateTime
)。
我认为最简单的解决scheme是设置
Created DATETIME2 NOT NULL DEFAULT GETDATE()
在列声明中并在VS2010 EntityModeldevise器中设置相应的列属性StoreGeneratedPattern = Computed 。
只需考虑在实体类的构造函数中设置它的值即可
public class Foo { public DateTime DateCreated { get; set; } public Foo() { DateCreated = DateTime.Now; } }
我需要一个UTC时间戳作为默认值,所以修改Daniel的解决scheme是这样的:
[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教程,请参阅这个真棒博客文章
创build一个新的属性类是一个很好的build议。 在我的情况下,我想指定“默认(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”。
目前你如何处理这个问题取决于你使用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 buisiness逻辑的信息。
public DateTime DateCreated { get { return (this.dateCreated == default(DateTime)) ? this.dateCreated = DateTime.Now : this.dateCreated; } set { this.dateCreated = value; } } private DateTime dateCreated = default(DateTime);
我知道这个post有点老,但有一个build议,可能会有所帮助。
我用一个枚举来确定在属性构造函数中设置什么。
财产声明:
[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
有一种方法。 添加这些类:
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作为属性的属性。 input到validation属性的值是“Now”,它将在运行时从使用Activator创build的DateTime实例中呈现。 源代码是从这个线程启发: https : //code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19 。 我改变它使我的类inheritance与DefaultValueAttribute而不是一个ValidationAttribute。
我想你可以使用StoreGeneratedPattern = Identity
(在模型devise器属性窗口中设置)来做到这一点。
我不会猜测那将是怎么做的,但是在试图弄清楚的时候,我注意到我的一些date列已经默认为CURRENT_TIMESTAMP()
,有些不是。 检查模型,我发现除了名称之外,两个列之间的唯一区别是获取默认值的那个名称将StoreGeneratedPattern
设置为Identity
。
我不会期望这样做,但阅读描述,这是有道理的:
确定在插入和更新操作期间是否自动生成数据库中的相应列。
此外,虽然这确实使数据库列有一个默认值“现在”,我想它并没有实际上将属性设置为POCO中的DateTime.Now
。 这对我来说不是一个问题,因为我有一个自定义的.tt文件,它已经将所有的date列自动设置为DateTime.Now
(实际上你不难自己修改.tt文件,特别是如果你有ReSharper并且得到一个语法突出的插件。(较新版本的VS可能已经语法高亮.tt文件,不知道。))
对我来说问题是:我如何获得数据库列有一个默认值,以便现有的查询,忽略该列将仍然工作? 而上述设置的工作。
我还没有testing过,但也有可能设置这将干扰设置你自己的显式值。 (我只是偶然发现了这个,因为EF6数据库首先为我写了这个模型。)
将以下添加到DateTime属性
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
我也想这个,想出了这个解决scheme(我只使用date部分 – 默认时间是没有意义的作为一个PropertyGrid默认):
public class DefaultDateAttribute : DefaultValueAttribute { public DefaultDateAttribute(short yearoffset) : base(DateTime.Now.AddYears(yearoffset).Date) { } }
这只是创build一个新的属性,你可以添加到你的DateTime属性。 例如,如果它默认为DateTime.Now.Date:
[DefaultDate(0)]