Установка значения по умолчанию для свойства DateTime в DateTime.Now внутри значения System.ComponentModel Default Attrbute
Кто-нибудь знает, как я могу указать значение по умолчанию для свойства DateTime, используя атрибут System.ComponentModel DefaultValue?
например, я пробую это:
[DefaultValue(typeof(DateTime),DateTime.Now.ToString("yyyy-MM-dd"))] public DateTime DateCreated { get; set; }
И он ожидает, что значение будет постоянным выражением.
- Место для размещения Database.SetInitializer
- Первые таблицы переходов EF5 и таблицы поиска
- Тип или имя пространства имен «DbContext» не удалось найти
- Передайте строку соединения кодовому первому DbContext
- Метод DbSet.Find смехотворно медленный по сравнению с .SingleOrDefault для ID
Это связано с использованием динамических данных ASP.NET. Я не хочу выравнивать столбец DateCreated, но просто поставляю DateTime.Now, если его нет. Я использую Entity Framework в качестве уровня данных
Ура,
Андрей
- Может ли кто-нибудь понять, почему я продолжаю получать эту ошибку, проверяя бета-версию EF 5
- Использование MySQL с платформой Entity Framework
- как обновить объект в Entity Framework 4 .NET
- SqlException из Entity Framework - новая транзакция не допускается, поскольку в сеансе есть другие streamи
- EF, включая другие объекты (шаблон общего репозитория)
- Список поставщиков Entity Framework для различных баз данных
- Entity Framework 6 Сначала код Значение по умолчанию
- Entity Framework с NOLOCK
Вы не можете сделать это с помощью атрибута, потому что это всего лишь метаинформация, сгенерированная во время компиляции. Просто добавьте код в конструктор для инициализации даты, если это необходимо, создайте триггер и обработайте отсутствующие значения в базе данных или внедрите getter таким образом, чтобы он возвращал DateTime.Now, если поле поддержки не инициализировано.
public DateTime DateCreated { get { return this.dateCreated.HasValue ? this.dateCreated.Value : DateTime.Now; } set { this.dateCreated = value; } } private DateTime? dateCreated = null;
Нет причин, по которым я могу придумать, что это невозможно сделать через атрибут. Возможно, это связано с отставанием Microsoft. Кто знает.
Лучшее решение, которое я нашел, – использовать параметр defaultValueSql в первой миграции кода.
CreateTable( "dbo.SomeTable", c => new { TheDateField = c.DateTime(defaultValueSql: "GETDATE()") });
Мне не нравится частое ссылочное решение по установке его в конструкторе classа сущности, потому что если что-либо, кроме Entity Framework, вставляет в эту таблицу запись, поле даты не получит значение по умолчанию. И идея использования триггера для обработки этого случая просто кажется мне неправильной.
Это возможно и довольно просто:
для DateTime.MinValue
[System.ComponentModel.DefaultValue(typeof(DateTime), "")]
для любого другого значения в качестве последнего аргумента DefaultValueAttribute
укажите строку, которая представляет желаемое значение DateTime.
Это значение должно быть постоянным выражением и требуется для создания объекта ( DateTime
) с использованием TypeConverter
.
Простым решением, если вы используете Entity Framework, является добавление парциального classа и определение конструктора для объекта, поскольку среда не определяет его. Например, если у вас есть объект с именем Example, вы должны поместить следующий код в отдельный файл.
namespace EntityExample { public partial class Example : EntityObject { public Example() { // Initialize certain default values here. this._DateCreated = DateTime.Now; } } }
Я думаю, что самым простым решением является установка
Created DATETIME2 NOT NULL DEFAULT GETDATE()
в объявлении столбца и в VS2010 Designer EntityModel задает соответствующее свойство столбца StoreGeneratedPattern = Computed .
Просто подумайте об установке его значения в конструкторе classа сущности
public class Foo { public DateTime DateCreated { get; set; } public Foo() { DateCreated = DateTime.Now; } }
Мне нужна отметка времени 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 см. Этот удивительный пост в блоге
Хорошим предложением является создание нового classа атрибутов. В моем случае я хотел указать «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 сериализатор JSON выводит «1/1/0001 12:00:00 AM», даже если была установлена опция DefaultValueHandling.Ignore.
Добавьте ниже свойство DateTime
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateCreated { get { return (this.dateCreated == default(DateTime)) ? this.dateCreated = DateTime.Now : this.dateCreated; } set { this.dateCreated = value; } } private DateTime dateCreated = default(DateTime);
Как вы справляетесь с этим в данный момент, зависит от того, какую модель вы используете Linq для 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.
Просто нашел, что это ищет что-то другое, но в новой версии C # вы можете использовать для этого еще более короткую версию:
public DateTime DateCreated { get; set; } = DateTime.Now;
Я знаю, что этот пост немного стар, но есть предложение, которое может помочь некоторым.
Я использовал 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
Enum:
Public Enum EInitialValue DateTime_Now DateTime_Min DateTime_Max End Enum
Есть выход. Добавьте эти classы:
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 { /// /// 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. /// [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; } } /// /// 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. /// /// Default value to render from an instance of 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() ?.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(); var value = (DateTime)instance.GetType() .GetProperty(this.DefaultValue) .GetValue(instance); return value; } private DateTime GetExtensionMethodValue() { var instance = Activator.CreateInstance (); 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 { /// /// Inspired from https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19. See usage for more information. /// 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 как атрибут ваших свойств. Значение для ввода вашего атрибута проверки – это такие вещи, как «Сейчас», которые будут отображаться во время выполнения из экземпляра DateTime, созданного с помощью Activator. Исходный код вдохновлен этим streamом: https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19 . Я изменил его, чтобы мой class наследовал с DefaultValueAttribute вместо ValidationAttribute.
Я думаю, что вы можете сделать это, используя StoreGeneratedPattern = Identity
(устанавливается в окне свойств дизайнера модели).
Я бы не догадался, что так будет, но, пытаясь понять это, я заметил, что некоторые из моих столбцов даты уже не выполняли CURRENT_TIMESTAMP()
а некоторые – нет. Проверяя модель, я вижу, что единственное различие между двумя столбцами, кроме имени, заключается в том, что тот, который получает значение по умолчанию, имеет значение StoreGeneratedPattern
для Identity
.
Я бы не ожидал, что это будет так, но, читая описание, это имеет смысл:
Определяет, будет ли автоматически создаваться соответствующий столбец в базе данных во время операций вставки и обновления.
Кроме того, в то время как это делает столбец базы данных значением по умолчанию «сейчас», я думаю, он фактически не устанавливает свойство DateTime.Now
в POCO. Это не было проблемой для меня, поскольку у меня есть настроенный файл .tt, который уже устанавливает все мои столбцы даты в DateTime.Now
автоматически (на самом деле нетрудно изменить сам файл .tt, особенно если у вас есть ReSharper и получить плагин подсветки синтаксиса. (Более новые версии VS могут уже синтаксически выделять файлы .tt, не уверены.))
Для меня была проблема: как мне получить столбец базы данных по умолчанию, чтобы существующие запросы, которые опускали этот столбец, все еще работают? И работа над этим работала.
Я еще не тестировал его, но также возможно, что установка этого будет мешать установке вашего собственного явного значения. (Я только наткнулся на это, в первую очередь, потому что EF6 Database First написала модель для меня таким образом.)
В C # версии 6 можно указать значение по умолчанию
public DateTime fieldname { get; set; } = DateTime.Now;
используя System.ComponentModel.DataAnnotations.Schema;
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime CreatedOn { get; private set; }
Я также хотел это и придумал это решение (я использую только часть даты – время по умолчанию не имеет смысла как по умолчанию для PropertyGrid):
public class DefaultDateAttribute : DefaultValueAttribute { public DefaultDateAttribute(short yearoffset) : base(DateTime.Now.AddYears(yearoffset).Date) { } }
Это просто создает новый атрибут, который вы можете добавить к свойству DateTime. Например, если по умолчанию используется DateTime.Now.Date:
[DefaultDate(0)]