การแปลงชนิดข้อมูล datetime2 เป็นชนิดข้อมูล datetime ทำให้ค่าอยู่นอกช่วง


174

ฉันมีรหัสต่อไปนี้ใน HomeController ของฉัน:

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");
}

และนี่คือมุมมองสำหรับวิธีการแก้ไข:

<% 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>

<% } %>

เมื่อฉันกดปุ่มส่งฉันได้รับข้อผิดพลาด: {"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."}ความคิดใด ๆ ที่เป็นปัญหาคืออะไร? ฉันสมมติว่าวิธีการแก้ไขพยายามอัปเดตค่าที่โพสต์ในฐานข้อมูลเป็นแก้ไข แต่ด้วยเหตุผลบางอย่างมันไม่ชอบ ... แม้ว่าฉันจะไม่เห็นว่าทำไมวันที่เกี่ยวข้องเนื่องจากไม่ได้กล่าวถึงใน วิธีการควบคุมเพื่อแก้ไข?


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

คำตอบ:


166

ปัญหาคือคุณกำลังใช้ApplyPropertyChangesกับวัตถุจำลองที่มีข้อมูลอยู่ในแบบฟอร์มเท่านั้น (พาดหัวเรื่องราวและรูปภาพ) ApplyPropertyChangesใช้การเปลี่ยนแปลงคุณสมบัติของวัตถุรวมถึงเตรียมDateTime, ซึ่งเป็นชุดที่ 0001-01-01 ซึ่งอยู่นอกช่วงของ SQL DATETIMEServer

แทนที่จะApplyPropertyChangesแนะนำให้ใช้ฉันขอแนะนำให้ดึงวัตถุที่กำลังแก้ไขเปลี่ยนฟิลด์เฉพาะที่แก้ไขแบบฟอร์มของคุณจากนั้นบันทึกวัตถุด้วยการแก้ไขเหล่านั้น ด้วยวิธีนี้เฉพาะการเปลี่ยนแปลงสาขาที่มีการแก้ไข อีกวิธีหนึ่งคุณสามารถวางอินพุตที่ซ่อนอยู่ในหน้าเว็บของคุณด้วยฟิลด์อื่น ๆ ที่บรรจุอยู่ แต่จะไม่เป็นมิตรกับการแก้ไขพร้อมกัน

ปรับปรุง:

นี่คือตัวอย่างที่ยังไม่ทดลองเพียงแค่อัปเดตบางฟิลด์ของออบเจ็กต์ของคุณ (ซึ่งสมมติว่าคุณใช้ LINQ เป็น 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();

มีประโยชน์มาก :) ฉันสงสัยว่าทำไมวันที่ถูกเปลี่ยนแปลงเมื่อฉันไม่ได้ระบุ คุณสามารถช่วยเปลี่ยนวิธีการแก้ไขจากนั้นจึงไม่ใช้ ApplyPropertyChanges ได้อีกต่อไป? ฉันยังใหม่กับ ASP.NET และไม่เข้าใจทุกอย่างในขณะนี้ ขอบคุณเพื่อน
คาเมรอน

จะทำอย่างไรถ้าฉันต้องการตั้งวันที่เป็นวันที่ปัจจุบันเช่น วันที่และเวลาที่บทความได้รับการอัปเดตหรือไม่ เนื่องจากอาจเป็นตัวเลือกที่ดีที่สุดและฉันคิดว่ามันจะทำงานกับ ApplyPropertyChanges ที่ฉันมีอยู่
คาเมรอน

เห็นการแก้ไขของฉัน (ก็สันนิษฐานว่าmodifiedDateเป็นชื่อของสถานที่ให้บริการของคุณ)
จาค็อบ

SubmitChanges ไม่ทำงานในแอพของฉัน: / เป็นไปได้หรือไม่ที่จะเพิ่มstory.modifiedDate = DateTime.Now;บิตลงในรหัสปัจจุบันของฉัน? ขอบคุณ
Cameron

1
ข้อผิดพลาดนี้เกิดขึ้นเมื่อเราตั้งค่า DateTime ที่สร้างขึ้นเป็นวันที่แทนที่จะเป็น DateTime สาธารณะ สร้างวันที่แล้วเนื่องจาก DateTime ไม่สามารถเป็นโมฆะได้ดังนั้นทำไมจึงเกิดข้อผิดพลาดในช่วง มันอาจมีประโยชน์ แต่ก็แก้ไขปัญหาของฉัน
adnan

115

นี่เป็นข้อผิดพลาดทั่วไปที่ผู้คนเผชิญเมื่อใช้ Entity Framework สิ่งนี้เกิดขึ้นเมื่อเอนทิตีที่เกี่ยวข้องกับตารางที่บันทึกมีฟิลด์ datetime ที่บังคับและคุณไม่ได้ตั้งค่าด้วยค่าบางค่า

วัตถุ datetime เริ่มต้นจะถูกสร้างขึ้นด้วยค่า01/01/1000และจะใช้แทนโมฆะ สิ่งนี้จะถูกส่งไปยังคอลัมน์ datetime ซึ่งสามารถเก็บค่าวันที่จาก1753-01-01 00:00:00เป็นต้นไป แต่ไม่ใช่ก่อนหน้านี้ซึ่งจะนำไปสู่ข้อยกเว้นนอกช่วง

ข้อผิดพลาดนี้สามารถแก้ไขได้โดยการแก้ไขฟิลด์ฐานข้อมูลเพื่อยอมรับ null หรือโดยการกำหนดค่าเริ่มต้นให้กับฟิลด์ด้วยค่า


3
สิ่งนี้จะเกิดขึ้นเมื่อฟิลด์ datetime ในฐานข้อมูลเป็นทางเลือกและไม่ได้ตั้งค่า ดังนั้นนี่ไม่ใช่ข้อผิดพลาดของคนทั่วไปนี่เป็นหนึ่งในปัญหาสถาปัตยกรรมของ EF
GSoft Consulting

1
ฉันเห็นด้วย EF ควรเห็นประเภทใน DB และปรับตามหรือโยนหรืออย่างน้อยก็โยนข้อผิดพลาดที่แม่นยำยิ่งขึ้น กลับหัวกลับหางฉันชอบคำตอบของคุณเนื่องจากคุณให้ 2 ตัวเลือกแทนตัวเลือกปกติ - เริ่มต้นการยื่นด้วยค่าขั้นต่ำ
DanteTheSmith

43

DATETIMEสนับสนุน 1753/1/1 ถึง "นิรันดร์" (9999/12/31) ในขณะที่ DATETIME2สนับสนุน 0001/1/1 ผ่านทางนิรันดร์

MSDN

คำตอบ: ฉันคิดว่าคุณลองบันทึกDateTimeด้วยค่า '0001/1/1' เพียงแค่ตั้งเบรกพอยต์และแก้ปัญหาถ้าเป็นเช่นนั้นแทนที่DateTimeด้วยnullหรือตั้งวันที่ปกติ


ฉันจะใส่อะไรในคอนโทรลเลอร์ การดีบักจะแสดงข้อผิดพลาดที่ฉันโพสต์ไว้ด้านบน ขอบคุณ
คาเมรอน

ดูเหมือนข้อผิดพลาดที่นี่ -> _db.SaveChanges (); คุณสามารถตั้งจุดพักก่อนที่จะสายนี้ ...
แอนดรู Orsich

ใช่ทำ จากนั้นมันก็บอกว่าพวกเขาเป็นข้อผิดพลาดใน SaveChanges ดังนั้นฉันดู InnerException และมันบอกว่าเป็นเพราะข้อผิดพลาดที่โพสต์ดังนั้นนั่นคือข้อผิดพลาด!
คาเมรอน

คุณตรวจสอบค่า DateTime ก่อน _db.SaveChanges (); ถูกเรียกว่า? มันยอดเยี่ยมมากกว่า '1753/1/1'
Andrew Orsich

ค่าวันที่ของบทความดั้งเดิมคือ {18/10/2009 00:00:00} และค่าวันที่ของ ArticleToEdit คือ {01/01/0001 00:00:00} ดังนั้นดูเหมือนว่าจะพยายามเปลี่ยนวันที่วันที่ 1 ของทุกอย่างที่ไม่ได้อยู่ ฉันต้องการ แต่ไม่ได้อธิบายว่าทำไมมันถึงเกิดข้อผิดพลาดเนื่องจากรูปแบบเหมือนกันใช่ไหม
คาเมรอน

14

อันนี้ทำให้ฉันบ้า ฉันต้องการหลีกเลี่ยงการใช้เวลาวันที่ nullable ( DateTime?) ฉันไม่มีตัวเลือกในการใช้ประเภท datetime2 ของ SQL 2008 อย่างใดอย่างหนึ่ง ( modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2");)

ในที่สุดฉันก็เลือกทำสิ่งต่อไปนี้:

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;
                    }
                }
            }
        }
    }
}

10

คุณสามารถแก้ไขปัญหานี้ได้ด้วยการเพิ่มรุ่น (Entity Framework version> = 5)

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

8

หากคุณมีคอลัมน์ที่เป็น datetime และอนุญาต null คุณจะได้รับข้อผิดพลาดนี้ ฉันแนะนำให้ตั้งค่าให้ส่งผ่านไปยังวัตถุก่อน. SaveChanges ();


5

ฉันได้รับข้อผิดพลาดนี้หลังจากเปลี่ยนโมเดล (รหัสแรก) ดังนี้:

public DateTime? DateCreated

ถึง

public DateTime DateCreated

แสดงแถวที่มีค่า Null ใน DateCreated ทำให้เกิดข้อผิดพลาดนี้ ดังนั้นฉันต้องใช้คำสั่ง SQL UPDATEด้วยตนเองเพื่อเริ่มต้นฟิลด์ด้วยค่ามาตรฐาน

โซลูชันอื่นอาจเป็นการระบุค่าเริ่มต้นสำหรับการยื่น


3

ในกรณีของฉันใน initializer จากคลาสที่ฉันใช้ในตารางของฐานข้อมูลฉันไม่ได้ตั้งค่าเริ่มต้นให้กับคุณสมบัติ DateTime ของฉันดังนั้นทำให้เกิดปัญหาที่อธิบายในคำตอบ @Andrew Orsich ดังนั้นฉันจึงทำให้คุณสมบัติเป็นโมฆะ หรือฉันอาจให้ DateTime ด้วยตอนนี้ในตัวสร้าง หวังว่าจะช่วยใครซักคน


3

ดูเหมือนว่าคุณกำลังใช้กรอบงานเอนทิตี วิธีแก้ปัญหาของฉันคือการเปลี่ยนคอลัมน์วันที่และเวลาทั้งหมดเป็นวันที่ 2 และใช้วันที่และเวลาในการสร้างคอลัมน์ใหม่ใด ๆ ในคำอื่น ๆ ทำให้ EF ใช้ datetime2 โดยค่าเริ่มต้น เพิ่มไปยังวิธี OnModelCreating ในบริบทของคุณ:

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

ที่จะได้รับ DateTime และ DateTime ทั้งหมดหรือไม่ คุณสมบัติของเอนทิตีทั้งหมดในโมเดลของคุณ


2

ฉันมีปัญหาเดียวกันโชคไม่ดีที่ฉันมีสองคุณสมบัติ DateTime ในรูปแบบของฉันและหนึ่งคุณสมบัติ DateTime เป็นโมฆะก่อนที่ฉันจะบันทึก SaveChanges

ดังนั้นตรวจสอบให้แน่ใจว่าแบบจำลองของคุณมีค่า DateTime ก่อนบันทึกการเปลี่ยนแปลงหรือทำให้เป็นโมฆะเพื่อป้องกันข้อผิดพลาด:

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

ดังนั้นนี่เป็นการแก้ปัญหาของฉันมันเป็นเรื่องของการทำให้แน่ใจว่าวันที่โมเดลของคุณถูกต้องก่อนที่จะคงอยู่กับฐานข้อมูล:

public DateTime DateAdded { get; set; }
public DateTime? ReleaseDate { get; set; }

2

หากคุณใช้รุ่น Entity Framework> = 5 ให้ใช้คำอธิบายประกอบ [DatabaseGenerated (DatabaseGeneratedOption.Computed)] กับ DateTime ของคุณในชั้นเรียนของคุณจะช่วยให้ทริกเกอร์ของตารางฐานข้อมูลทำงานได้โดยป้อนวันที่เพื่อสร้างบันทึกและอัปเดตบันทึก รหัส Entity Framework ของคุณเพื่อปิดปาก

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

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

นี้คล้ายกับคำตอบที่ 6 เขียนโดย Dongolo Jeno และแก้ไขโดย Gille Q.


1

นอกจากนี้หากคุณไม่ทราบส่วนของรหัสที่เกิดข้อผิดพลาดคุณสามารถโปรไฟล์การประมวลผล sql "ไม่ดี" โดยใช้ sql profiler ที่รวมกับ mssql

พารามิเตอร์ datetime ที่ไม่ดีจะแสดงผลดังนี้:

พารามิเตอร์ไม่ดี


1

ปัญหานี้มักเกิดขึ้นเมื่อคุณพยายามอัพเดตเอนทิตี ตัวอย่างเช่นคุณมีหน่วยงานที่มีข้อมูลที่เรียกว่าDateCreatedซึ่งเป็น[จำเป็น]และเมื่อคุณแทรกบันทึกไม่มีข้อผิดพลาดจะถูกส่งกลับ แต่เมื่อคุณต้องการที่จะปรับปรุงกิจการโดยเฉพาะอย่างยิ่งคุณได้รับ

การแปลง datetime2 ผิดพลาดนอกช่วง

ตอนนี้นี่คือทางออก:

ในมุมมองการแก้ไขของคุณedit.cshtmlสำหรับผู้ใช้ MVC สิ่งที่คุณต้องทำคือการเพิ่มฟิลด์แบบฟอร์มที่ซ่อนอยู่DateCreatedใต้ช่องที่ซ่อนอยู่สำหรับคีย์หลักของข้อมูลการแก้ไข

ตัวอย่าง:

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

การเพิ่มสิ่งนี้ไปยังมุมมองการแก้ไขของคุณคุณจะไม่มีข้อผิดพลาดที่ฉันรับรองกับคุณ


1

คุณต้องเปิดใช้งานค่า Null สำหรับตัวแปรวันที่ของคุณ:

 public Nullable<DateTime> MyDate{ get; set; }

0

ลองทำให้ทรัพย์สินของคุณเป็นโมฆะ

    public DateTime? Time{ get; set; }

ทำงานให้ฉัน


0

หากคุณไม่ได้เข้าถึงฐานข้อมูลคุณสามารถเปลี่ยนประเภทคอลัมน์ฐานข้อมูลจาก datetime เป็น datetime2 (7) มันจะยังคงส่งวัตถุ datetime และมันจะถูกบันทึกไว้


0

ตัวแบบควรมีวันที่และเวลาว่าง เมธอดที่แนะนำก่อนหน้านี้ในการดึงข้อมูลอ็อบเจ็กต์ที่ต้องถูกแก้ไขควรใช้แทน ApplyPropertyChanges ในกรณีของฉันฉันมีวิธีนี้เพื่อบันทึกวัตถุของฉัน:

public ActionResult Save(QCFeedbackViewModel item)

จากนั้นในการให้บริการฉันดึงข้อมูลโดยใช้:

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

รหัสการให้บริการเต็มรูปแบบมีดังนี้:

 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();

0

[แก้ไข] ในรหัส Framework เอนทิตีแรก (กรณีของฉัน) เพิ่งเปลี่ยนDateTimeเพื่อDateTime?แก้ปัญหาของฉัน

/*from*/ public DateTime SubmitDate { get; set; }
/*to  */ public DateTime? SubmitDate { get; set; }

0

ข้อผิดพลาด: การแปลงชนิดข้อมูล datetime2 เป็นชนิดข้อมูล datetime ทำให้ค่าอยู่นอกช่วง

ข้อผิดพลาดนี้เกิดขึ้นเมื่อเนื่องจากไม่กำหนดค่าใด ๆ กับคอลัมน์วันที่เป็นค่าว่างใน SQL DB โดยใช้ EF และได้รับการแก้ไขโดยการกำหนดค่าเดียวกัน

หวังว่านี่จะช่วยได้!


0

รับปัญหานี้เมื่อสร้างคลาสของฉันจากฐานข้อมูลวิธีแรก แก้ไขโดยใช้เพียงแค่ Convert.DateTime (dateCausingProblem) ที่จริงแล้วพยายามแปลงค่าก่อนที่จะผ่านมันช่วยให้คุณประหยัดจากค่าที่ไม่คาดคิด


0

คุณต้องจับคู่รูปแบบการป้อนข้อมูลของฟิลด์วันที่ของคุณกับรูปแบบเอนทิตีที่ต้องการซึ่งก็คือ yyyy / mm / dd


1
มีคำตอบอื่น ๆ ที่ให้คำถามของ OP และพวกเขาโพสต์เมื่อไม่นาน เมื่อโพสต์คำตอบดู: ฉันจะเขียนคำตอบที่ดีได้อย่างไร โปรดตรวจสอบให้แน่ใจว่าคุณได้เพิ่มโซลูชันใหม่หรือคำอธิบายที่ดีขึ้นอย่างมากโดยเฉพาะเมื่อตอบคำถามรุ่นเก่า
help-info.de
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.