Apakah ada yang tahu bagaimana saya dapat menentukan nilai Default untuk properti DateTime menggunakan Atribut DefaultValue System.ComponentModel?
misalnya saya coba ini:
[DefaultValue(typeof(DateTime),DateTime.Now.ToString("yyyy-MM-dd"))]
public DateTime DateCreated { get; set; }
Dan itu mengharapkan nilainya menjadi ekspresi konstan.
Ini dalam konteks penggunaan dengan Data Dinamis ASP.NET. Saya tidak ingin menancapkan kolom DateCreated tetapi hanya menyediakan DateTime.Now jika tidak ada. Saya menggunakan Entity Framework sebagai Lapisan Data saya
Bersulang,
Andrew
sumber
get
dapat disederhanakan menjadi:return dateCreated ?? DateTime.Now;
Tambahkan di bawah ke properti DateTime
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
sumber
Tidak ada alasan saya dapat menyimpulkan bahwa hal itu tidak mungkin dilakukan melalui atribut. Mungkin ada di backlog Microsoft. Siapa tahu.
Solusi terbaik yang saya temukan adalah menggunakan parameter defaultValueSql dalam migrasi kode pertama.
CreateTable( "dbo.SomeTable", c => new { TheDateField = c.DateTime(defaultValueSql: "GETDATE()") });
Saya tidak suka solusi referensi yang sering mengaturnya di konstruktor kelas entitas karena jika ada selain Entity Framework yang menempelkan catatan di tabel itu, bidang tanggal tidak akan mendapatkan nilai default. Dan gagasan menggunakan pemicu untuk menangani kasus itu sepertinya salah bagi saya.
sumber
Saya telah menguji ini pada EF inti 2.1
Di sini Anda tidak dapat menggunakan Konvensi atau Anotasi Data. Anda harus menggunakan 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()"); } }
Dokumen resmi
sumber
Ini mungkin dan cukup sederhana:
untuk
DateTime.MinValue
[System.ComponentModel.DefaultValue(typeof(DateTime), "")]
untuk nilai lain sebagai argumen terakhir dari
DefaultValueAttribute
menentukan string yang mewakili nilai DateTime yang diinginkan.Nilai ini harus berupa ekspresi konstan dan diperlukan untuk membuat object (
DateTime
) menggunakanTypeConverter
.sumber
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)
Solusi sederhana jika Anda menggunakan Entity Framework adalah dengan menambahkan kelas partikal dan menentukan konstruktor untuk entitas karena kerangka tidak menentukannya. Misalnya jika Anda memiliki entitas bernama Contoh, Anda akan meletakkan kode berikut di file terpisah.
namespace EntityExample { public partial class Example : EntityObject { public Example() { // Initialize certain default values here. this._DateCreated = DateTime.Now; } } }
sumber
Saya pikir solusi termudah adalah mengatur
Created DATETIME2 NOT NULL DEFAULT GETDATE()
dalam deklarasi kolom dan desainer VS2010 EntityModel mengatur properti kolom yang sesuai StoreGeneratedPattern = Computed .
sumber
Membuat kelas atribut baru adalah saran yang bagus. Dalam kasus saya, saya ingin menentukan 'default (DateTime)' atau 'DateTime.MinValue' sehingga serializer Newtonsoft.Json akan mengabaikan anggota DateTime tanpa nilai yang sebenarnya.
[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 ) ) { } }
Tanpa atribut DefaultValue, serializer JSON akan mengeluarkan "1/1/0001 12:00:00 AM" meskipun opsi DefaultValueHandling.Ignore telah disetel.
sumber
Cukup pertimbangkan untuk menetapkan nilainya di konstruktor kelas entitas Anda
public class Foo { public DateTime DateCreated { get; set; } public Foo() { DateCreated = DateTime.Now; } }
sumber
Datetime
properti nullable sebelum melakukan ini.Saya membutuhkan Stempel Waktu UTC sebagai nilai default dan karenanya mengubah solusi Daniel seperti ini:
[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();
Untuk tutorial DateRangeAttribute, lihat posting blog yang luar biasa ini
sumber
menggunakan System.ComponentModel.DataAnnotations.Schema;
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime CreatedOn { get; private set; }
sumber
Ada jalan. Tambahkan kelas-kelas ini:
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); } }
Dan gunakan DefaultDateTimeValue sebagai atribut ke properti Anda. Nilai yang akan dimasukkan ke atribut validasi Anda adalah hal-hal seperti "Sekarang", yang akan ditampilkan pada waktu proses dari instance DateTime yang dibuat dengan Activator. Kode sumber terinspirasi dari utas ini: https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19 . Saya mengubahnya untuk membuat kelas saya mewarisi dengan DefaultValueAttribute daripada ValidationAttribute.
sumber
Baru saja menemukan ini mencari sesuatu yang berbeda, tetapi di versi C # yang baru, Anda dapat menggunakan versi yang lebih pendek untuk itu:
public DateTime DateCreated { get; set; } = DateTime.Now;
sumber
Saya menghadapi masalah yang sama, tetapi yang paling berhasil untuk saya adalah di bawah ini:
public DateTime CreatedOn { get; set; } = DateTime.Now;
sumber
public DateTime DateCreated { get { return (this.dateCreated == default(DateTime)) ? this.dateCreated = DateTime.Now : this.dateCreated; } set { this.dateCreated = value; } } private DateTime dateCreated = default(DateTime);
sumber
Bagaimana Anda menangani hal ini saat ini bergantung pada model apa yang Anda gunakan Linq ke SQL atau EntityFramework?
Di L2S Anda bisa menambahkan
public partial class NWDataContext { partial void InsertCategory(Category instance) { if(Instance.Date == null) Instance.Data = DateTime.Now; ExecuteDynamicInsert(instance); } }
EF sedikit lebih rumit, lihat http://msdn.microsoft.com/en-us/library/cc716714.aspx untuk info lebih lanjut tentang logika buisiness EF.
sumber
Saya tahu posting ini agak tua, tetapi memiliki saran yang mungkin membantu beberapa.
Saya menggunakan Enum untuk menentukan apa yang harus diatur di konstruktor atribut.
Deklarasi properti:
[DbProperty(initialValue: EInitialValue.DateTime_Now)] public DateTime CreationDate { get; set; }
Konstruktor properti:
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:
sumber
Saya pikir Anda bisa melakukan ini dengan menggunakan
StoreGeneratedPattern = Identity
(diatur di jendela properti perancang model).Saya tidak akan menyangka bahwa itu akan menjadi cara melakukannya, tetapi ketika mencoba untuk mengetahuinya saya perhatikan bahwa beberapa kolom tanggal saya sudah default
CURRENT_TIMESTAMP()
dan beberapa tidak. Memeriksa model, saya melihat bahwa satu-satunya perbedaan antara dua kolom selain nama adalah yang mendapatkan nilai default telahStoreGeneratedPattern
diatur keIdentity
.Saya tidak menyangka akan seperti itu, tetapi membaca deskripsinya, agak masuk akal:
Selain itu, meskipun ini membuat kolom database memiliki nilai default "sekarang", saya rasa ini tidak benar-benar mengatur properti untuk berada
DateTime.Now
di POCO. Ini tidak menjadi masalah bagi saya karena saya memiliki file .tt yang disesuaikan yang sudah mengatur semua kolom tanggal sayaDateTime.Now
secara otomatis (sebenarnya tidak sulit untuk memodifikasi file .tt sendiri, terutama jika Anda memiliki ReSharper dan mendapatkan penyorotan sintaks plugin. (Versi VS yang lebih baru mungkin sudah menyorot file .tt sintaks, tidak yakin.))Masalah bagi saya adalah: bagaimana cara membuat kolom database memiliki default sehingga kueri yang sudah ada yang menghilangkan kolom itu akan tetap berfungsi? Dan pengaturan di atas berfungsi untuk itu.
Saya belum mengujinya tetapi mungkin juga pengaturan ini akan mengganggu pengaturan nilai eksplisit Anda sendiri. (Saya hanya tersandung pada ini di tempat pertama karena EF6 Database First menulis model untuk saya seperti ini.)
sumber
Dalam C # Versi 6 dimungkinkan untuk memberikan nilai default
public DateTime fieldname { get; set; } = DateTime.Now;
sumber
Dengan EF 7:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] Column(TypeName = "datetime2")] DateTime? Dateadded { get; set; }
skrip migrasi:
AlterColumn("myschema.mytable", "Dateadded", c => c.DateTime(nullable: false, precision: 7, storeType: "datetime2", defaultValueSql: "getutcdate()"));
hasil:
sumber
Saya juga menginginkan ini dan menghasilkan solusi ini (saya hanya menggunakan bagian tanggal - waktu default tidak masuk akal sebagai default PropertyGrid):
public class DefaultDateAttribute : DefaultValueAttribute { public DefaultDateAttribute(short yearoffset) : base(DateTime.Now.AddYears(yearoffset).Date) { } }
Ini hanya membuat atribut baru yang dapat Anda tambahkan ke properti DateTime Anda. Misalnya jika defaultnya adalah DateTime.Now.Date:
[DefaultDate(0)]
sumber