Saya menggunakan DbContext dan Code First API yang diperkenalkan dengan Entity Framework 4.1.
Model data menggunakan tipe data dasar seperti string
dan DateTime
. Satu-satunya anotasi data yang saya gunakan dalam beberapa kasus adalah [Required]
, tetapi itu tidak ada di DateTime
properti mana pun. Contoh:
public virtual DateTime Start { get; set; }
The DbContext subclass juga sederhana dan terlihat seperti:
public class EventsContext : DbContext
{
public DbSet<Event> Events { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Event>().ToTable("Events");
}
}
The initializer set tanggal dalam model dengan nilai-nilai yang masuk akal baik tahun ini atau tahun depan.
Namun ketika saya menjalankan penginisialisasi, saya mendapatkan kesalahan ini di context.SaveChanges()
:
Konversi tipe data datetime2 ke tipe data datetime menghasilkan nilai di luar rentang. Pernyataan tersebut telah dihentikan.
Saya tidak mengerti mengapa ini terjadi sama sekali karena semuanya sangat sederhana. Saya juga tidak yakin bagaimana cara memperbaikinya karena tidak ada file edmx untuk diedit.
Ada ide?
sumber
Jawaban:
Anda harus memastikan bahwa Mulai lebih besar dari atau sama dengan SqlDateTime.MinValue (1 Januari 1753) - secara default Mulai sama dengan DateTime.MinValue (1 Januari 0001).
sumber
Sederhana. Pada kode Anda terlebih dahulu, setel jenis DateTime ke DateTime ?. Jadi Anda bisa bekerja dengan tipe DateTime nullable dalam database. Contoh entitas:
public class Alarme { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public DateTime? DataDisparado { get; set; }//.This allow you to work with nullable datetime in database. public DateTime? DataResolvido { get; set; }//.This allow you to work with nullable datetime in database. public long Latencia { get; set; } public bool Resolvido { get; set; } public int SensorId { get; set; } [ForeignKey("SensorId")] public virtual Sensor Sensor { get; set; } }
sumber
Dalam beberapa kasus,
DateTime.MinValue
(atau setara,default(DateTime)
) digunakan untuk menunjukkan nilai yang tidak diketahui.Metode penyuluhan sederhana ini dapat membantu menangani situasi seperti itu:
public static class DbDateHelper { /// <summary> /// Replaces any date before 01.01.1753 with a Nullable of /// DateTime with a value of null. /// </summary> /// <param name="date">Date to check</param> /// <returns>Input date if valid in the DB, or Null if date is /// too early to be DB compatible.</returns> public static DateTime? ToNullIfTooEarlyForDb(this DateTime date) { return (date >= (DateTime) SqlDateTime.MinValue) ? date : (DateTime?)null; } }
Pemakaian:
sumber
Anda dapat membuat kolom menjadi null, jika itu sesuai dengan masalah pemodelan spesifik Anda. Tanggal nol tidak akan dipaksakan ke tanggal yang tidak berada dalam rentang jenis SQL DateTime seperti nilai default. Pilihan lainnya adalah memetakan secara eksplisit ke jenis yang berbeda, mungkin dengan,
.HasColumnType("datetime2")
sumber
Meskipun pertanyaan ini cukup lama dan sudah ada jawaban yang bagus, saya pikir saya harus mengajukan satu lagi yang menjelaskan 3 pendekatan berbeda untuk menyelesaikan masalah ini.
Pendekatan Pertama
Memetakan
DateTime
properti secara eksplisitpublic virtual DateTime Start { get; set; }
kedatetime2
dalam kolom yang sesuai dalam tabel. Karena secara default EF akan memetakannyadatetime
.Ini dapat dilakukan dengan API atau anotasi data yang lancar.
API Lancar
Di kelas DbContext, overide
OnModelCreating
dan konfigurasi propertiStart
(untuk alasan penjelasan, ini adalah properti kelas EntityClass).protected override void OnModelCreating(DbModelBuilder modelBuilder) { //Configure only one property modelBuilder.Entity<EntityClass>() .Property(e => e.Start) .HasColumnType("datetime2"); //or configure all DateTime Preperties globally(EF 6 and Above) modelBuilder.Properties<DateTime>() .Configure(c => c.HasColumnType("datetime2")); }
Anotasi data
[Column(TypeName="datetime2")] public virtual DateTime Start { get; set; }
Pendekatan ke-2
Inisialisasi
Start
ke nilai default dalam konstruktor EntityClass. Ini bagus karena jika karena alasan tertentu nilaiStart
tidak disetel sebelum menyimpan entitas ke dalam database mulai akan selalu memiliki nilai default. Pastikan nilai default lebih besar dari atau sama dengan SqlDateTime.MinValue (dari 1 Januari 1753 hingga 31 Desember 9999)public class EntityClass { public EntityClass() { Start= DateTime.Now; } public DateTime Start{ get; set; } }
Pendekatan ke-3
Buat
Start
menjadi tipe nullableDateTime
-catatan?
setelahDateTime
-public virtual DateTime? Start { get; set; }
Untuk penjelasan lebih lanjut baca posting ini
sumber
Jika
DateTime
properti Anda nullable dalam database, pastikan untuk menggunakanDateTime?
properti objek terkait atau EF akan meneruskanDateTime.MinValue
untuk nilai yang tidak ditetapkan yang berada di luar rentang yang dapat ditangani oleh tipe datetime SQL.sumber
Solusi saya adalah mengalihkan semua kolom datetime ke datetime2, dan menggunakan datetime2 untuk kolom baru. Dengan kata lain, buat EF menggunakan datetime2 secara default. Tambahkan ini ke metode OnModelCreating pada konteks Anda:
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
Itu akan mendapatkan semua DateTime dan DateTime? properti di semua entitas Anda.
sumber
menginisialisasi properti Start di konstruktor
Ini bekerja untuk saya ketika saya mencoba untuk menambahkan beberapa bidang baru ke tabel Pengguna ASP .Net Identity Framework (AspNetUsers) menggunakan Kode Pertama. Saya memperbarui Class - ApplicationUser di IdentityModels.cs dan saya menambahkan field lastLogin jenis DateTime.
public class ApplicationUser : IdentityUser { public ApplicationUser() { CreatedOn = DateTime.Now; LastPassUpdate = DateTime.Now; LastLogin = DateTime.Now; } public String FirstName { get; set; } public String MiddleName { get; set; } public String LastName { get; set; } public String EmailId { get; set; } public String ContactNo { get; set; } public String HintQuestion { get; set; } public String HintAnswer { get; set; } public Boolean IsUserActive { get; set; } //Auditing Fields public DateTime CreatedOn { get; set; } public DateTime LastPassUpdate { get; set; } public DateTime LastLogin { get; set; } }
sumber
Berdasarkan jawaban pengguna @ andygjp, lebih baik jika Anda mengganti basis
Db.SaveChanges()
metode dan menambahkan fungsi untuk mengganti tanggal mana pun yang tidak berada di antara SqlDateTime.MinValue dan SqlDateTime.MaxValue.Berikut ini contoh kode
public class MyDb : DbContext { public override int SaveChanges() { UpdateDates(); return base.SaveChanges(); } private void UpdateDates() { foreach (var change in ChangeTracker.Entries().Where(x => (x.State == EntityState.Added || x.State == EntityState.Modified))) { var values = change.CurrentValues; foreach (var name in values.PropertyNames) { var value = values[name]; if (value is DateTime) { var date = (DateTime)value; if (date < SqlDateTime.MinValue.Value) { values[name] = SqlDateTime.MinValue.Value; } else if (date > SqlDateTime.MaxValue.Value) { values[name] = SqlDateTime.MaxValue.Value; } } } } } }
Diambil dari komentar pengguna @ sky-dev di https://stackoverflow.com/a/11297294/9158120
sumber
Saya memiliki masalah yang sama dan dalam kasus saya, saya mengatur tanggal ke DateTime () baru, bukan DateTime. Sekarang
sumber
Dalam kasus saya ini terjadi ketika saya menggunakan entitas dan tabel sql memiliki nilai default dari datetime == getdate (). jadi apa yang saya lakukan untuk menetapkan nilai ke bidang ini.
sumber
Saya menggunakan Database First dan ketika kesalahan ini terjadi pada saya, solusi saya adalah memaksa ProviderManifestToken = "2005" di file edmx (membuat model kompatibel dengan SQL Server 2005). Tidak tahu apakah sesuatu yang serupa dimungkinkan untuk Code First.
sumber
Satu baris memperbaiki ini:
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
Jadi, dalam kode saya, saya menambahkan:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2")); }
Menambahkan satu baris itu ke subclass DBContext menimpa bagian OnModelCreating void seharusnya berfungsi.
sumber
Dalam kasus saya, setelah beberapa refactoring di EF6, pengujian saya gagal dengan pesan kesalahan yang sama seperti poster asli tetapi solusi saya tidak ada hubungannya dengan bidang DateTime.
Saya baru saja kehilangan bidang wajib saat membuat entitas. Setelah saya menambahkan bidang yang hilang, kesalahannya hilang. Entitas saya memang memiliki dua DateTime? bidang tapi itu bukan masalah.
sumber