Konversi tipe data datetime2 ke tipe data datetime menghasilkan nilai di luar kisaran

379

Saya memiliki data dengan 5 kolom, di mana baris diisi dengan data kemudian disimpan ke database melalui transaksi.

Saat menyimpan, kesalahan dikembalikan:

Konversi tipe data datetime2 ke tipe data datetime menghasilkan nilai di luar kisaran

Ini menyiratkan, sebagaimana telah dibaca, bahwa data saya memiliki tipe DateTime2dan database saya a DateTime; itu salah.

Kolom tanggal disetel DateTimeseperti ini:

new DataColumn("myDate", Type.GetType("System.DateTime"))

Pertanyaan

Apakah ini dapat diselesaikan dalam kode atau apakah ada sesuatu yang harus diubah pada tingkat database?

Gerbrand
sumber

Jawaban:

60

Tanggal seperti apa yang Anda miliki di kolom?

Apakah semuanya cocok dalam kisaran tipe?


Selain itu, cara yang benar untuk mendapatkan Typeobjek untuk DataColumnkonstruktor adalah typeofkata kunci, yang urutan besarnya lebih cepat.

Karena itu, untuk membuat kolom, Anda harus menulis

new DataColumn("myDate", typeof(DateTime))
Slaks
sumber
3
Saya mengubah kolom data saya dan menggunakan typeof sekarang ... Selanjutnya saya menemukan masalah saya. ada 1 datarow yang berisi tanggal yang salah, yang memicu kesalahan
Gerbrand
739

Ini bisa terjadi jika Anda tidak menetapkan nilai ke bidang DateTime ketika bidang tidak menerima nilai NULL .

Itu memperbaikinya bagi saya!

andyuk
sumber
43
Dalam Kerangka Entitas, jika Anda menambahkan kolom Dibuat yang bukan nol, perbarui EDMX Anda, saat Anda tidak menetapkan nilai dalam kode, yang dapat melempar kesalahan ini dengan cara ini
Brad Thomas
6
Apa yang memperbaikinya untuk Anda? Kesalahan ini muncul ketika Anda memiliki bidang datetime dengan panggilan getdate () sebagai nilai default.
user3046061
15
Mengapa Kerangka Entitas tidak dapat mengabaikan jika NULL karena di sisi SQL saya, saya memiliki nilai default = getdate ()?
JoshYates1980
33
Apa yang saya percaya itu terjadi adalah EntityFramework melihat DateTime.MinValue yang merupakan tahun 0001 dan dalam SQL datetime berada di luar nilai rentang, sehingga mengirimkan nilai ini sebagai nilai DateTime2 (yang mendukung tahun 0001) sehingga memasukkan / memperbarui valid, namun gagal ketika SQL mencoba untuk mengubah DateTime2 ini menjadi DateTime karena ini akan menghasilkan nilai yang berbeda. Dua solusi adalah: 1 Gunakan datetime nullable dalam model Anda atau 2. inisialisasi semua nilai datetime Anda, ke nilai yang benar sebelum menyimpan perubahan konteks. Pilihan yang Anda buat tergantung pada apa arti datetime dalam model Anda.
Guillermo Ruffino
1
@ Solusi GuillermoRuffino bekerja untuk saya. Periksa semua bidang Anda dan temukan entri 0001 tahun itu.
Francesco B.
158

Baik peta DATETIMEdan dalam. NET - Anda tidak dapat benar-benar melakukan "konversi", karena benar-benar jenis .NET yang sama.DATETIME2System.DateTime

Lihat halaman dokumen MSDN: http://msdn.microsoft.com/en-us/library/bb675168.aspx

Ada dua nilai berbeda untuk " SqlDbType" untuk keduanya - dapatkah Anda menentukannya dalam DataColumndefinisi Anda ?

TETAPI: di SQL Server, rentang tanggal yang didukung sangat berbeda.

DATETIMEmendukung 1753/1/1 hingga "keabadian" (9999/12/31), sementara DATETIME2mendukung 0001/1/1 hingga keabadian.

Jadi apa yang benar-benar perlu Anda lakukan adalah memeriksa tahun tanggal - jika sebelum 1753, Anda perlu mengubahnya menjadi sesuatu SETELAH 1753 agar DATETIMEkolom di SQL Server untuk menanganinya.

Marc

marc_s
sumber
7
Ini menjelaskan masalah yang saya miliki. Meskipun ada beberapa situasi di mana tanggal nyata sebelum 1753/1/1 perlu ditangani, tetapi ada banyak situasi di mana seseorang mendapatkan nilai default 0001/1/1 yang dapat mengakibatkan kesalahan.
Hong
Saya mengonfirmasi bahwa ketika saya mencoba untuk memasukkan tipe data DateTime baru () ke tipe data 'datetime' saya menerima pengecualian ini.
George Onofrei
1
Saya mencoba untuk menetapkan nilai default DateTime.MinValue dalam kode C # saya yang menulis ke database. Ini menjelaskan kesalahan yang saya dapatkan. +1
Mkalafut
Saya menggunakan Kode Entitas Kerangka Pertama dan saya menggunakan model dengan properti DateTime. DtInit = new System.DateTime(1492, 10, 12),gagal
Kiquenet
Ini adalah salah satu situasi di mana alasan sebenarnya tersembunyi di balik tambalan ... +1
Eugenio Miró
41

Dalam database SQL Server 2008 saya, saya memiliki DateTimekolom yang ditandai sebagai tidak dapat dibatalkan, tetapi dengan GetDate()fungsi sebagai nilai default. Ketika menyisipkan objek baru menggunakan EF4, saya mendapatkan kesalahan ini karena saya tidak meneruskan properti DateTime pada objek saya secara eksplisit. Saya mengharapkan fungsi SQL untuk menangani tanggal untuk saya tetapi tidak. Solusi saya adalah mengirim nilai tanggal dari kode alih-alih mengandalkan database untuk menghasilkannya.

obj.DateProperty = DateTime.now; // C#
Graham
sumber
2
Senang untuk membantu. Ini menjengkelkan karena Anda akan berpikir konteks data EF akan dapat menemukan bahwa bidang tersebut memiliki nilai default ketika objek dibuat dari tabel.
Graham
Saya akan memikirkan banyak hal tentang EF. Saya menggunakan entitas pelacakan diri POCO dan itu adalah sebuah cluster. Saya akan memeriksa kode model pertama, dan jika itu juga penuh omong kosong saya serius berpikir untuk kembali ke LINQ ke sql dan menggunakan objek mapper untuk memetakan alat peraga ke entitas saya sendiri ...
2
Saya melihat demo Kode EF Pertama di VS Live 2 minggu yang lalu dan itu terlihat LUAR BIASA, btw.
Graham
Itu kabar baik. Kami akan segera memulai proyek baru di kantor saya, dan saya berpisah pada EF-CF dan necis (digunakan / dikelola oleh SO). Mungkin akan turun ke mana yang lebih baik dalam aplikasi yang digunakan melalui layanan WCF.
1
Halo, komentar tahun lalu! Saya sendiri memulai dengan EF Code-First dan menemukan bahwa pada POCO saya, saya hanya perlu mendefinisikan anggota datetime saya Nullable<DateTime>, dan dalam kode saya dapat membiarkan ini benar-benar nol (bukan 01/01/0000). Saya terkejut melihat bahwa EF to SQL tahu untuk mengabaikan null ini pada INSERT dan menggunakan tanggal dari server ( GetDate()) ... Bagi kami ini bahkan lebih baik karena kami membutuhkan konsistensi yang lebih baik pada server, tanpa khawatir tentang perbedaan jam antara server web dan server sql.
Funka
34

bagi saya itu karena datetime itu ..

01/01/0001 00:00:00

dalam hal ini Anda ingin menetapkan nol untuk Anda EF DateTime Object ... menggunakan kode FirstYearRegistered saya sebagai contoh

DateTime FirstYearRegistered = Convert.ToDateTime(Collection["FirstYearRegistered"]);
if (FirstYearRegistered != DateTime.MinValue)
{
    vehicleData.DateFirstReg = FirstYearRegistered;
}  
JGilmartin
sumber
Saya mem-parsing data ini menggunakan ExcelDataReader dan mengembalikan 01/01/0001 ketika teks yang tidak valid dimasukkan (tidak membuang pengecualian seperti yang diharapkan - menggunakan metode .GetDateTime (columnIndex)). Perbandingan dengan MinValue melakukan trik untuk mencegah pengecualian di luar rentang dalam sql.
Tommy
22

Yang ini membuatku gila. Saya ingin menghindari menggunakan waktu tanggal nullable ( DateTime?). Saya juga tidak memiliki opsi untuk menggunakan datetime2tipe SQL Server 2008

modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2");

Saya akhirnya memilih yang berikut:

public class MyDb : DbContext
{
    public override int SaveChanges()
    {
        UpdateDates();
        return base.SaveChanges();
    }

    private void UpdateDates()
    {
        foreach (var change in ChangeTracker.Entries<MyEntityBaseClass>())
        {
            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;
                    }
                }
            }
        }
    }
}
langit-dev
sumber
1
Menggunakan [Column(TypeName = "datetime2")]?
Kiquenet
21

Terkadang EF tidak tahu yang berurusan dengan kolom yang dikomputasi atau pemicu . Sesuai desain, operasi tersebut akan menetapkan nilai di luar EF setelah disisipkan.

Cara mengatasinya adalah menentukan Computeddi EF edmxuntuk kolom itu diStoreGeneratedPattern properti.

Bagi saya ketika kolom memiliki pemicu yang memasukkan tanggal dan waktu saat ini, lihat di bawah di bagian ketiga.


Langkah-langkah Untuk Menyelesaikan

Dalam Visual Studio buka Model Browserhalaman Modellalu Entity Types-> lalu

  1. Pilih entitas dan properti waktu tanggal
  2. Pilih StoreGeneratedPattern
  3. Mulai Computed

Dialog Tipe Model Browser Model EF


Untuk situasi ini, jawaban lain adalah solusi, untuk tujuan kolom adalah untuk memiliki waktu / tanggal yang ditentukan ketika catatan dibuat, dan itu adalah tugas SQL untuk menjalankan pemicu untuk menambah waktu yang tepat. Seperti pemicu SQL ini:

DEFAULT (GETDATE()) FOR [DateCreated].

GamegaMan
sumber
Perhatikan bahwa saya telah menggunakan GETDATE()yang saya benar-benar lakukan pada saat itu. Tapi ada komentar baru-baru ini yang harus digunakan SYSDATETIME()untuk operasi DateTime2 yang saya yakini benar.
ΩmegaMan
10

Saya mengalami ini dan menambahkan berikut ini ke properti datetime saya:

 [Column(TypeName = "datetime2")]
 public DateTime? NullableDateTimePropUtc { get; set; }
Rogala
sumber
1
using System.ComponentModel.DataAnnotations.Schema; diperlukan
Kiquenet
9

Jika kami tidak melewatkan waktu tanggal ke bidang waktu tanggal, tanggal default {1/1/0001 12:00:00 AM} akan diteruskan.

Tetapi tanggal ini tidak kompatibel dengan kerangka kerja entitas sehingga akan dibuang konversi tipe data datetime2 ke tipe data datetime menghasilkan nilai di luar rentang

Hanya default DateTime.nowke bidang tanggal jika Anda tidak melewatkan tanggal apa pun.

movie.DateAdded = System.DateTime.Now
Lijo
sumber
Saya akan mengatakan melewati 'DateTime.Now' sebagai nilai default jauh dari benar, dan agak menyesatkan.
Bartosz
6

Hal termudah adalah mengubah database Anda untuk menggunakan datetime2 daripada datetime. Kompatibilitas berfungsi dengan baik, dan Anda tidak akan mendapatkan kesalahan.

Anda masih ingin melakukan banyak pengujian ...

Kesalahannya mungkin karena Anda mencoba menetapkan tanggal ke tahun 0 atau sesuatu - tetapi semuanya tergantung pada di mana Anda memiliki kendali untuk mengubah barang.

Rob Farley
sumber
4

Saya menemukan posting ini mencoba mencari tahu mengapa saya terus mendapatkan kesalahan berikut yang dijelaskan oleh jawaban lain.

Konversi tipe data datetime2 ke tipe data datetime menghasilkan nilai di luar kisaran.

Gunakan objek DateTime yang dapat dibatalkan.
DateTime publik? PurchaseDate {get; set; }

Jika Anda menggunakan kerangka kerja, atur properti nullable di file edmx ke True

Setel properti nullable dalam file edmx ke ** Benar **

bau
sumber
3

Seperti yang telah ditunjukkan oleh andyuk , ini bisa terjadi ketika nilai NULL ditetapkan ke bidang DateTime yang tidak dapat dibatalkan . Pertimbangkan untuk mengubah DateTime ke DateTime? atau Nullable < DateTime >. Ingatlah bahwa, jika Anda menggunakan Properti Ketergantungan , juga harus memastikan bahwa tipe properti dependensi Anda juga merupakan tipe DateTime yang dapat dibatalkan.

Di bawah ini adalah contoh kehidupan nyata dari DateTime ke DateTime yang tidak lengkap ? penyesuaian tipe yang memunculkan perilaku aneh

masukkan deskripsi gambar di sini

Julio Nobre
sumber
2

Entity Framework 4 berfungsi dengan tipe data datetime2 sehingga dalam db bidang terkait harus datetime2 untuk SQL Server 2008.

Untuk mencapai solusi ada dua cara.

  1. Untuk menggunakan tipe data datetime di Entity Framwork 4 Anda harus mengganti ProviderManifestToken di file-edmx ke "2005".
  2. Jika Anda menyetel bidang yang sesuai sebagai Bolehkan Null (dikonversi ke NULLABLE) maka EF secara otomatis menggunakan objek tanggal sebagai datetime.
Mahmut C
sumber
1
Saya mengambil poin kedua Anda untuk model database saya (kelas POCO) dan bertanya-tanya bagaimana cara mengatur bidang sebagai tipe yang dapat dibatalkan. Jika ada yang bertanya-tanya, Anda dapat melakukan ini dengan menambahkan Tanda Tanya (?) Setelah jenis tanggal. misalnya DateTime publik? StartTime {get; set; } Ini memecahkan masalah bagi saya. Satu-satunya hal lain yang harus saya lakukan adalah meletakkan TimeSpan yang dilemparkan di sekitar baris kode di mana saya mengurangi dua nilai DateTime yang dapat dibatalkan satu sama lain. mis. var timeTaken = (TimeSpan) (endTime - startTime);
Ciaran Gallagher
1

Menciptakan kelas dasar berdasarkan implementasi @ sky-dev. Jadi ini dapat dengan mudah diterapkan ke berbagai konteks, dan entitas.

public abstract class BaseDbContext<TEntity> : DbContext where TEntity : class
{
    public BaseDbContext(string connectionString)
        : base(connectionString)
    {
    }
    public override int SaveChanges()
    {

        UpdateDates();
        return base.SaveChanges();
    }

    private void UpdateDates()
    {
        foreach (var change in ChangeTracker.Entries<TEntity>())
        {
            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;
                    }
                }
            }
        }
    }
}

Pemakaian:

public class MyContext: BaseDbContext<MyEntities>
{

    /// <summary>
    /// Initializes a new instance of the <see cref="MyContext"/> class.
    /// </summary>
    public MyContext()
        : base("name=MyConnectionString")
    {
    }
    /// <summary>
    /// Initializes a new instance of the <see cref="MyContext"/> class.
    /// </summary>
    /// <param name="connectionString">The connection string.</param>
    public MyContext(string connectionString)
        : base(connectionString)
    {
    }

     //DBcontext class body here (methods, overrides, etc.)
 }
dynamiclynk
sumber
1

Tambahkan atribut yang disebutkan di bawah pada properti di kelas model Anda.

Attribute = [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
Reference = System.ComponentModel.DataAnnotations.Schema

Awalnya saya lupa menambahkan atribut ini. Jadi dalam database saya kendala dibuat seperti

ALTER TABLE [dbo].[TableName] ADD DEFAULT (getdate()) FOR [ColumnName]

dan saya menambahkan atribut ini dan memperbarui db saya kemudian diubah menjadi

ALTER TABLE [dbo].[TableName] ADD CONSTRAINT [DF_dbo.TableName_ColumnName] DEFAULT (getdate()) FOR [ColumnName]
Ajith Chandran
sumber
[DatabaseGenerated (DatabaseGeneratedOption.Computed)]
Ajith Chandran
0

Terkadang ini berfungsi dengan baik pada mesin pengembangan dan tidak di server. Dalam kasus saya, saya harus mengatakan:

<globalization uiCulture="es" culture="es-CO" />

Di file web.config.

Zona waktu di mesin (Server) benar (ke lokasi CO) tetapi aplikasi web tidak. Pengaturan ini dilakukan dan berfungsi dengan baik lagi.

Tentu saja, semua tanggal memiliki nilai.

: D

Jaime Enrique Espinosa Reyes
sumber
0

Menambahkan kode ini ke kelas di ASP.NET bekerja sama dengan saya:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}
Howie Krauth
sumber
0

Saya menyadari masalah ini dan Anda semua seharusnya juga:

https://en.wikipedia.org/wiki/Year_2038_problem

Dalam SQL tipe bidang baru dibuat untuk menghindari masalah ini (datetime2).

Jenis bidang 'Tanggal' ini memiliki nilai rentang yang sama dengan kelas .Net DateTime. Ini akan menyelesaikan semua masalah Anda, jadi saya pikir cara terbaik untuk menyelesaikannya adalah mengubah jenis kolom basis data Anda (itu tidak akan mempengaruhi data tabel Anda).

marcolomew
sumber
0

Periksa dua berikut: 1) Bidang ini tidak memiliki nilai NULL. Sebagai contoh:

 public DateTime MyDate { get; set; }

Ganti ke:

public DateTime MyDate { get; set; }=DateTime.Now;

2) Baru database lagi. Sebagai contoh:

db=new MyDb();
RainyTears
sumber
Bagaimana jika Anda tidak ingin nilainya menjadi DateTime. Sekarang secara default?
Savage
Jika Anda tidak ingin: DateTime.Now. Anda dapat menggunakan: DateTime baru (..., ..., ...)
RainyTears
0

Masalah dengan atribut datetime yang diwarisi

Pesan kesalahan ini sering ditampilkan ketika bidang tanggal yang tidak dapat dibatalkan memiliki nilai nol pada waktu memasukkan / memperbarui. Salah satu penyebabnya adalah warisan.

Jika tanggal Anda diwariskan dari kelas dasar dan Anda tidak membuat pemetaan, EF tidak akan membaca nilainya.

Untuk informasi lebih lanjut: https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and- memilih-strategi-pedoman

FrankyHollywood
sumber
0

Saya melihat kesalahan ini ketika saya ingin mengedit halaman menggunakan ASP.Net MVC. Saya tidak punya masalah saat Membuat tetapi Memutakhirkan Database membuat properti DateCreated saya di luar jangkauan!

Ketika Anda tidak ingin DateTimeProperti Anda dapat dibatalkan dan tidak ingin memeriksa apakah nilainya ada dalam rentang DateTime sql (dan @Html.HiddenFortidak membantu!), Cukup tambahkan static DateTimebidang di dalam kelas terkait (Pengontrol) dan berikan nilai saat GET sedang beroperasi kemudian gunakan ketika POST melakukan tugasnya:

public class PagesController : Controller
{
    static DateTime dateTimeField;
    UnitOfWork db = new UnitOfWork();

    // GET:
    public ActionResult Edit(int? id)
    {
        Page page = db.pageRepository.GetById(id);
        dateTimeField = page.DateCreated;
        return View(page);
    }

    // POST: 
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(Page page)
    {
        page.DateCreated = dateTimeField;
        db.pageRepository.Update(page);
        db.Save();
        return RedirectToAction("Index");

    }
}
mp3846
sumber
0

Saya mengalami masalah ini pada proyek aplikasi konsol sederhana dan solusi cepat saya adalah mengubah setiap tanggal datetime2 yang mungkin menjadi datetime nullable dengan menjalankan metode ini:

static DateTime? ParseDateTime2(DateTime? date)
    {
        if (date == null || date.ToString() == "1/1/0001 12:00:00 AM")
        {
            return null;
        }
        else
        {
            return date;
        }
    }

Ini jelas bukan metode yang sepenuhnya komprehensif, tetapi ini bekerja untuk kebutuhan saya dan mungkin itu akan membantu orang lain!

David Alan Condit
sumber
0

Periksa format req dalam DB. misalnya DB saya memiliki nilai Default atau Binding(((1)/(1))/(1900))

System.DateTime MyDate = new System.DateTime( 1900 ,1, 1);

masukkan deskripsi gambar di sini

Arsalan Maqsood
sumber
-1

Anda akan memiliki kolom tanggal yang ditetapkan untuk lesathan nilai min dattime yang diizinkan seperti 1/1/1001.

untuk mengatasi masalah ini Anda dapat mengatur nilai datetime yang tepat untuk properti Anda dan juga mengatur properti ajaib lainnya seperti IsSpecified = true.

Koteshwar
sumber