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

174

Saya memiliki kode berikut di HomeController saya:

public ActionResult Edit(int id)
{
    var ArticleToEdit = (from m in _db.ArticleSet where m.storyId == id select m).First();
    return View(ArticleToEdit);
}

[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Article ArticleToEdit)
{
    var originalArticle = (from m in _db.ArticleSet where m.storyId == ArticleToEdit.storyId select m).First();
    if (!ModelState.IsValid)
        return View(originalArticle);

    _db.ApplyPropertyChanges(originalArticle.EntityKey.EntitySetName, ArticleToEdit);
    _db.SaveChanges();
    return RedirectToAction("Index");
}

Dan ini adalah tampilan untuk metode Edit:

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="headline">Headline</label>
            <%= Html.TextBox("headline") %>
        </p>
        <p>
            <label for="story">Story <span>( HTML Allowed )</span></label>
            <%= Html.TextArea("story") %>
        </p>
        <p>
            <label for="image">Image URL</label>
            <%= Html.TextBox("image") %>
        </p>
        <p>
            <input type="submit" value="Post" />
        </p>
    </fieldset>

<% } %>

Ketika saya menekan tombol kirim saya mendapatkan kesalahan: {"The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated."}Ada ide apa masalahnya? Saya berasumsi bahwa metode edit mencoba memperbarui nilai yang diposting di DB ke yang diedit tetapi untuk beberapa alasan itu tidak menyukainya ... Meskipun saya tidak melihat mengapa tanggal terlibat karena tidak disebutkan dalam metode pengontrol untuk diedit?

Cameron
sumber
1
modelBuilder.Entity<WorldInfo>().Property(d => d.CurrentTime).HasColumnType("datetime2");
Anthony Nichols

Jawaban:

166

Masalahnya adalah bahwa Anda menggunakan ApplyPropertyChangesdengan objek model yang hanya diisi dengan data dalam bentuk (informasi utama, cerita, dan gambar). ApplyPropertyChangesberlaku perubahan untuk semua properti objek, termasuk Anda diinisialisasi DateTime, yang diatur ke 0001-01-01, yang berada di luar jangkauan SQL Server DATETIME.

Daripada menggunakan ApplyPropertyChanges , saya sarankan mengambil objek yang sedang dimodifikasi, mengubah bidang spesifik suntingan formulir Anda, kemudian menyimpan objek dengan modifikasi tersebut; dengan cara itu, hanya bidang yang diubah yang dimodifikasi. Bergantian, Anda dapat menempatkan input tersembunyi di halaman Anda dengan bidang lain yang terisi, tetapi itu tidak akan sangat ramah dengan pengeditan bersamaan.

Memperbarui:

Berikut ini contoh yang belum diuji dari hanya memperbarui beberapa bidang objek Anda (ini dengan asumsi Anda menggunakan LINQ ke SQL):

var story = _db.ArticleSet.First(a => a.storyId == ArticleToEdit.storyId);
story.headline = ArticleToEdit.headline;
story.story = ArticleToEdit.story;
story.image = ArticleToEdit.image;
story.modifiedDate = DateTime.Now;
_db.SubmitChanges();
Yakub
sumber
Sangat membantu :) Saya bertanya-tanya mengapa tanggalnya diubah ketika saya tidak menentukannya. Bisakah Anda membantu mengubah metode Edit sehingga tidak lagi menggunakan ApplyPropertyChanges? Karena saya baru mengenal ASP.NET dan tidak sepenuhnya memahami semuanya saat ini. Terima kasih sobat.
Cameron
Bagaimana jika saya ingin mengatur tanggal ke tanggal saat ini yaitu. datetime bahwa artikel telah diperbarui? Karena itu mungkin akan menjadi pilihan terbaik dan saya kira itu akan bekerja dengan ApplyPropertyChanges yang saya mainkan.
Cameron
Lihat hasil edit saya (diasumsikan itu modifiedDateadalah nama properti Anda)
Jacob
SubmitChanges tidak berfungsi di Aplikasi saya: / apakah mungkin menambahkan story.modifiedDate = DateTime.Now;bit ke kode saya saat ini? Terima kasih
Cameron
1
kesalahan ini terjadi ketika kita menetapkan DateTime publik CreatedDate alih-alih DateTime publik? CreatedDate, karena DateTime tidak bisa nol, jadi mengapa ini memberikan kesalahan rentang. mungkin membantu, tetapi itu menyelesaikan masalah saya.
adnan
115

Ini adalah kesalahan umum yang dihadapi orang saat menggunakan Entity Framework. Ini terjadi ketika entitas yang terkait dengan tabel yang disimpan memiliki bidang datetime wajib dan Anda tidak menyetelnya dengan beberapa nilai.

Objek datetime default dibuat dengan nilai 01/01/1000dan akan digunakan sebagai pengganti nol. Ini akan dikirim ke kolom datetime yang dapat menyimpan nilai tanggal dari 1753-01-01 00:00:00seterusnya, tetapi tidak sebelumnya, yang mengarah ke pengecualian di luar jangkauan.

Kesalahan ini dapat diatasi dengan memodifikasi bidang basis data untuk menerima nol atau dengan menginisialisasi bidang dengan nilai.

Sanjay Kumar Madhva
sumber
3
Ini terjadi ketika bidang datetime dalam database adalah opsional dan nilai tidak diatur. Karenanya ini bukan kesalahan umum orang, ini adalah salah satu masalah arsitektur EF.
GSoft Consulting
1
Saya setuju EF harus melihat tipe dalam DB dan menyesuaikan sesuai atau melempar atau setidaknya melemparkan kesalahan yang lebih tepat. Sisi baiknya, saya suka jawaban Anda karena Anda memberikan 2 opsi dan bukan yang biasa - inisialisasi yang diajukan dengan nilai minimum.
DanteTheSmith
43

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

Nyonya

Jawaban: Saya kira Anda mencoba menyimpan DateTimedengan nilai '0001/1/1'. Cukup atur breakpoint dan debug, jika demikian gantikan DateTimedengan nullatau atur tanggal normal.

Andrew Orsich
sumber
Apa yang saya masukkan ke Controller? Debugging hanya memunculkan kesalahan yang telah saya posting di atas. Terima kasih.
Cameron
tampaknya ada kesalahan di sini -> _db.SaveChanges (); Anda dapat mengatur breakpoint sebelum baris ini ...
Andrew Orsich
Ya benar. Kemudian dikatakan mereka adalah kesalahan pada SaveChanges jadi saya melihat InnerException dan mengatakan itu karena kesalahan yang diposting jadi itu kesalahannya!
Cameron
Apakah Anda memeriksa nilai DateTime sebelum _db.SaveChanges (); telah dipanggil? Seharusnya lebih bagus dari '1753/1/1'.
Andrew Orsich
Nilai tanggal originalartikel adalah {18/10/2009 00:00:00} dan nilai tanggal ArticleToEdit adalah {01/01/0001 00:00:00} sehingga sepertinya berusaha mengubah tanggal ke 1 dari semua yang tidak Saya ingin saya ingin tetapi tidak menjelaskan mengapa itu melempar kesalahan karena formatnya sama kan?
Cameron
14

Yang ini membuatku gila. Saya ingin menghindari menggunakan waktu tanggal nullable ( DateTime?). Saya tidak memiliki opsi untuk menggunakan tipe datetime2 SQL 2008 baik (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
10

Anda juga dapat memperbaiki masalah ini dengan menambahkan ke model (versi Entity Framework> = 5)

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreationDate { get; set; }
Dongolo Jeno
sumber
8

Jika Anda memiliki kolom yang merupakan datetime dan memungkinkan nol, Anda akan mendapatkan kesalahan ini. Saya merekomendasikan pengaturan nilai untuk meneruskan ke objek sebelum .SaveChanges ();

Patrick
sumber
5

Saya mendapatkan kesalahan ini setelah saya mengubah model saya (kode pertama) sebagai berikut:

public DateTime? DateCreated

untuk

public DateTime DateCreated

Baris saat ini dengan nilai nol di DateCreated menyebabkan kesalahan ini. Jadi saya harus menggunakan Pernyataan UPDATE SQL secara manual untuk menginisialisasi bidang dengan nilai standar.

Solusi lain dapat berupa penetapan nilai default untuk yang diajukan.

Aleksandr Khomenko
sumber
3

Dalam kasus saya, dalam initializer dari kelas yang saya gunakan di tabel database, saya tidak menetapkan nilai default apa pun untuk properti DateTime saya, karena itu mengakibatkan masalah yang dijelaskan dalam jawaban @Andrew Orsich. Jadi saya baru saja membuat properti menjadi nullable. Atau saya juga bisa memberikannya DateTime. Sekarang di konstruktor. Semoga ini bisa membantu seseorang.

StinkyCat
sumber
3

Sepertinya Anda menggunakan kerangka entitas. Solusi saya adalah mengganti semua kolom datetime ke datetime2, dan menggunakan datetime2 untuk kolom baru apa pun, dengan kata lain membuat 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 pada semua entitas dalam model Anda.

Ogglas
sumber
2

Saya memiliki masalah yang sama, sayangnya, saya memiliki dua properti DateTime pada model saya dan satu properti DateTime adalah nol sebelum saya melakukan SaveChanges.

Jadi pastikan model Anda memiliki nilai DateTime sebelum menyimpan perubahan atau membuatnya nullable untuk mencegah kesalahan:

public DateTime DateAdded { get; set; }   //This DateTime always has a value before persisting to the database.
public DateTime ReleaseDate { get; set; }  //I forgot that this property doesn't have to have DateTime, so it will trigger an error

Jadi ini memecahkan masalah saya, ini masalah memastikan tanggal model Anda sudah benar sebelum bertahan ke database:

public DateTime DateAdded { get; set; }
public DateTime? ReleaseDate { get; set; }
Willy David Jr
sumber
2

Jika Anda menggunakan versi Entity Framework> = 5 lalu menerapkan [DatabaseGenerated (DatabaseGeneratedOption.Computed)] anotasi ke properti DateTime Anda di kelas Anda akan memungkinkan pemicu tabel database untuk melakukan tugasnya memasukkan tanggal untuk pembuatan catatan dan memperbarui catatan tanpa menyebabkan kode Kerangka Entitas Anda untuk muntah.

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateCreated { get; set; }

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateUpdated { get; set; }

Ini mirip dengan jawaban ke-6, yang ditulis oleh Dongolo Jeno dan Diedit oleh Gille Q.

Jim Kay
sumber
1

Juga, jika Anda tidak tahu bagian dari kode di mana kesalahan terjadi, Anda dapat memprofilkan eksekusi "buruk" sql menggunakan sql profiler yang diintegrasikan ke mssql.

Param datetime yang buruk akan menampilkan sesuatu seperti itu:

param buruk

Nigrimmist
sumber
1

Masalah ini biasanya terjadi ketika Anda mencoba memperbarui entitas. Misalnya Anda memiliki suatu entitas yang berisi bidang yang disebut DateCreatedyang [Diperlukan] dan ketika Anda memasukkan record, tidak ada kesalahan dikembalikan tetapi ketika Anda ingin Perbarui bahwa entitas tertentu, Anda mendapatkan

konversi datetime2 di luar rentang kesalahan.

Sekarang ini solusinya:

Pada tampilan edit Anda, yaitu edit.cshtmluntuk pengguna MVC semua yang perlu Anda lakukan adalah menambahkan bidang formulir tersembunyi untuk Anda DateCreatedtepat di bawah bidang tersembunyi untuk kunci utama dari data edit.

Contoh:

@Html.HiddenFor(model => model.DateCreated)

Menambahkan ini ke tampilan edit Anda, Anda tidak akan pernah memiliki kesalahan itu saya jamin.

Aduwu Joseph
sumber
1

Anda harus mengaktifkan nilai nol untuk variabel tanggal Anda:

 public Nullable<DateTime> MyDate{ get; set; }
Badr Bellaj
sumber
0

Coba buat properti Anda nullable.

    public DateTime? Time{ get; set; }

Bekerja untukku.

typhon04
sumber
0

Jika Anda memiliki akses ke DB, Anda dapat mengubah jenis kolom DB dari datetime ke datetime2 (7) itu masih akan mengirim objek datetime dan itu akan disimpan

Sergiu Mindras
sumber
0

Model harus memiliki datetime nullable. Metode yang disarankan sebelumnya untuk mengambil objek yang harus dimodifikasi harus digunakan sebagai pengganti ApplyPropertyChanges. Dalam kasus saya, saya memiliki metode ini untuk Menyimpan objek saya:

public ActionResult Save(QCFeedbackViewModel item)

Dan kemudian dalam layanan, saya mengambil menggunakan:

RETURNED = item.RETURNED.HasValue ? Convert.ToDateTime(item.RETURNED) : (DateTime?)null 

Kode layanan lengkap adalah sebagai berikut:

 var add = new QC_LOG_FEEDBACK()
            {

                QCLOG_ID = item.QCLOG_ID,
                PRE_QC_FEEDBACK = item.PRE_QC_FEEDBACK,
                RETURNED = item.RETURNED.HasValue ? Convert.ToDateTime(item.RETURNED) : (DateTime?)null,
                PRE_QC_RETURN = item.PRE_QC_RETURN.HasValue ? Convert.ToDateTime(item.PRE_QC_RETURN) : (DateTime?)null,
                FEEDBACK_APPROVED = item.FEEDBACK_APPROVED,
                QC_COMMENTS = item.QC_COMMENTS,
                FEEDBACK = item.FEEDBACK
            };

            _context.QC_LOG_FEEDBACK.Add(add);
            _context.SaveChanges();
anu
sumber
0

[Diselesaikan] Dalam Kode Entitas Kerangka Pertama (kasus saya) baru saja berubah DateTimeuntuk DateTime?menyelesaikan masalah saya.

/*from*/ public DateTime SubmitDate { get; set; }
/*to  */ public DateTime? SubmitDate { get; set; }
Amir Astaneh
sumber
0

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

Kesalahan ini terjadi ketika karena TIDAK menetapkan nilai apa pun terhadap kolom tanggal TIDAK NULL dalam SQL DB menggunakan EF dan diselesaikan dengan menetapkan yang sama.

Semoga ini membantu!

pengguna2964808
sumber
0

Mendapat masalah ini ketika membuat kelas saya dari pendekatan Database First. Dipecahkan dengan hanya menggunakan Convert.DateTime (dateCausingProblem) Bahkan, selalu mencoba untuk mengkonversi nilai sebelum melewati, Ini menyelamatkan Anda dari nilai yang tidak terduga.

Ansar nisar Gill
sumber
0

Anda harus mencocokkan format input bidang tanggal Anda dengan format entitas yang diperlukan yaitu yyyy / mm / dd

marc
sumber
1
Ada jawaban lain yang memberikan pertanyaan OP, dan mereka diposting beberapa waktu lalu. Saat mengirim jawaban, lihat: Bagaimana saya menulis jawaban yang baik? , harap pastikan Anda menambahkan solusi baru, atau penjelasan yang jauh lebih baik, terutama saat menjawab pertanyaan yang lebih lama.
help-info.de