Установка значения по умолчанию свойства DateTime в DateTime.Теперь внутри системы.ComponentModel Значение По Умолчанию Attrbute
кто-нибудь знает, как я могу указать значение по умолчанию для свойства DateTime с помощью системы.Атрибут ComponentModel DefaultValue?
например, я попробую это:
[DefaultValue(typeof(DateTime),DateTime.Now.ToString("yyyy-MM-dd"))]
public DateTime DateCreated { get; set; }
и он ожидает, что значение должно быть константным выражением.
это в контексте использования с ASP.NET динамические данные. Я не хочу строить столбец DateCreated, а просто предоставить DateTime.Теперь, если его нет. Я использую Entity Framework в качестве своих данных Слой
спасибо,
Андрей
19 ответов
вы не можете сделать это с атрибутом, потому что это просто метаинформация, сгенерированная во время компиляции. Просто добавьте код в конструктор, чтобы при необходимости инициализировать дату, создать триггер и обработать отсутствующие значения в базе данных или реализовать геттер таким образом, чтобы он возвращал DateTime.Теперь, если поле backing не инициализировано.
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()")
});
мне не нравится часто ссылочное решение установки его в конструкторе класса сущностей, потому что, если что-либо, кроме Entity Framework вставляет запись в эту таблицу, поле даты не получит значение по умолчанию значение. И идея использовать спусковой крючок, чтобы справиться с этим делом, кажется мне неправильной.
можно и довольно просто:
на DateTime.MinValue
[System.ComponentModel.DefaultValue(typeof(DateTime), "")]
для любого другого значения в качестве последнего аргумента DefaultValueAttribute
укажите строку, представляющую желаемое значение DateTime.
это значение должно быть постоянным выражением и требуется для создания объекта (DateTime
) через TypeConverter
.
простым решением при использовании Entity Framework является добавление класса partical и определение конструктора для сущности, поскольку платформа не определяет его. Например, если у вас есть объект с именем 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 EntityModel задайте соответствующее свойство столбца StoreGeneratedPattern = Вычисляемые.
просто рассмотреть его значение в конструкторе класса объекта
public class Foo
{
public DateTime DateCreated { get; set; }
public Foo()
{
DateCreated = DateTime.Now;
}
}
Мне нужна была метка времени UTC в качестве значения по умолчанию, и поэтому я изменил решение Даниэля следующим образом:
[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 см. В разделе это удивительное сообщение в блоге
создание нового класса атрибутов является хорошим предложением. В моем случае я хотел указать "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.Установлен параметр игнорировать.
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 to SQL или EntityFramework?
в L2S вы можете добавить
public partial class NWDataContext
{
partial void InsertCategory(Category instance)
{
if(Instance.Date == null)
Instance.Data = DateTime.Now;
ExecuteDynamicInsert(instance);
}
}
эф немного сложнее увидеть http://msdn.microsoft.com/en-us/library/cc716714.aspx подробнее о эф логика бизнеса.
просто нашел это, ища что-то другое, но в новой версии C# вы можете использовать еще более короткую версию для этого:
public DateTime DateCreated { get; set; } = DateTime.Now;
Я знаю, что этот пост немного старый, но есть предложение, которое может помочь некоторым.
Я использовал перечисление, чтобы определить, что установить в конструкторе атрибутов.
объявление :
[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 в качестве атрибута ваших свойств. Значение для ввода атрибута проверки-это такие вещи, как" сейчас", которые будут отображаться во время выполнения из экземпляра DateTime, созданного с помощью активатора. Исходный код вдохновлен этим потоком: https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19. Я изменил его, чтобы мой класс наследовал с DefaultValueAttribute вместо ValidationAttribute.
Я думаю вы можете сделать это с помощью StoreGeneratedPattern = Identity
(задайте в окне свойств модели конструктора).
Я бы не догадался, что это будет так, но, пытаясь понять это, я заметил, что некоторые из моих столбцов даты уже по умолчанию CURRENT_TIMESTAMP()
а некоторые нет. Проверяя модель, я вижу, что единственная разница между двумя столбцами, кроме имени, заключается в том, что тот, кто получает значение по умолчанию, имеет StoreGeneratedPattern
значение Identity
.
I не ожидал, что это будет так, но, читая описание, это имеет смысл:
определяет, будет ли соответствующий столбец в базе данных автоматически генерироваться во время операций вставки и обновления.
кроме того, хотя это делает столбец базы данных имеет значение по умолчанию "сейчас", я думаю, что на самом деле он не устанавливает свойство DateTime.Now
в поко. Это не было проблемой для меня, поскольку у меня есть настроенный.TT файл, который уже устанавливает все мои столбцы даты в DateTime.Now
автоматически (это на самом деле не трудно изменить .TT файл самостоятельно, особенно если у вас есть ReSharper и получить плагин подсветки синтаксиса. (Более новые версии VS могут уже выделить синтаксис.файлы tt, не уверен.))
проблема для меня была: как мне получить столбец базы данных по умолчанию, чтобы существующие запросы, которые опускают этот столбец, все еще работали? И вышеприведенная настройка сработала для этого.
Я еще не тестировал его, но это также возможно, что установка этого будет мешать установке вашего собственного явного значения. (Я только наткнулся на это в первую очередь, потому что база данных EF6 сначала написала модель для меня таким образом.)
В C# версии 6 можно указать значение по умолчанию
public DateTime fieldname { get; set; } = DateTime.Now;
использование системы.ComponentModel.DataAnnotations.Схема;
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedOn { get; private set; }
Я проверил это на EF core 2.1
здесь нельзя использовать ни соглашения, ни аннотации данных. Вы должны использовать свободно 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()");
}
}
Я также хотел этого и придумал это решение (я использую только часть даты - время по умолчанию не имеет смысла как значение по умолчанию PropertyGrid):
public class DefaultDateAttribute : DefaultValueAttribute {
public DefaultDateAttribute(short yearoffset)
: base(DateTime.Now.AddYears(yearoffset).Date) {
}
}
Это просто создает новый атрибут, который вы можете добавить в свое свойство DateTime. Е. Г. если это значение по умолчанию для типа datetime.Сейчас.Дата:
[DefaultDate(0)]