Việc chuyển đổi kiểu dữ liệu datetime2 thành kiểu dữ liệu datetime dẫn đến giá trị ngoài phạm vi


174

Tôi có đoạn mã sau trong HomeContoder của mình:

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

Và đây là chế độ xem cho phương thức Chỉnh sửa:

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

<% } %>

Khi tôi nhấn nút gửi, tôi nhận được lỗi: {"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."}Bất kỳ ý tưởng nào là vấn đề? Tôi giả sử rằng phương pháp chỉnh sửa đang cố cập nhật giá trị được đăng trong DB thành chỉnh sửa trên nhưng vì một số lý do, nó không thích nó ... Mặc dù tôi không hiểu tại sao ngày đó có liên quan vì nó không được đề cập trong Phương pháp điều khiển để chỉnh sửa?


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

Câu trả lời:


166

Vấn đề là bạn đang sử dụng ApplyPropertyChangesvới một đối tượng mô hình chỉ được điền dữ liệu ở dạng (tiêu đề, câu chuyện và hình ảnh). ApplyPropertyChangesáp dụng các thay đổi cho tất cả các thuộc tính của đối tượng, bao gồm cả chưa được khởi tạo của bạn DateTime, được đặt thành 0001-01-01, nằm ngoài phạm vi của SQL Server DATETIME.

Thay vì sử dụng ApplyPropertyChanges, tôi khuyên bạn nên truy xuất đối tượng đang được sửa đổi, thay đổi các trường cụ thể mà biểu mẫu của bạn chỉnh sửa, sau đó lưu đối tượng bằng các sửa đổi đó; theo cách đó, chỉ các trường thay đổi được sửa đổi. Thay phiên, bạn có thể đặt các đầu vào ẩn trong trang của mình với các trường khác được điền, nhưng điều đó sẽ không thân thiện với các chỉnh sửa đồng thời.

Cập nhật:

Đây là một mẫu chưa được kiểm tra về việc chỉ cập nhật một số trường của đối tượng của bạn (điều này giả sử bạn đang sử dụng LINQ to 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();

Rất hữu ích :) Tôi đã tự hỏi tại sao ngày bị thay đổi khi tôi không chỉ định nó. Bạn có thể giúp thay đổi phương thức Chỉnh sửa để nó không còn sử dụng ApplyPropertyChanges không? Vì tôi chưa quen với ASP.NET và không hiểu hết về nó vào lúc này. Cảm ơn bạn
Cameron

Điều gì sẽ xảy ra nếu tôi muốn đặt ngày thành ngày hiện tại tức là. datetime mà bài báo đã được cập nhật? Vì đó có lẽ sẽ là lựa chọn tốt nhất và tôi cho rằng nó sẽ hoạt động với ApplyPropertyChanges tôi có trong trò chơi.
Cameron

Xem bản chỉnh sửa của tôi (giả sử đó modifiedDatelà tên tài sản của bạn)
Jacob

SendChanges không hoạt động trong Ứng dụng của tôi: / có thể thêm story.modifiedDate = DateTime.Now;bit vào mã hiện tại của tôi không? Cảm ơn
Cameron

1
lỗi này xảy ra khi chúng ta đặt DateTime createdDate công khai thay vì DateTime công khai? CreatedDate, vì DateTime không thể là null, vậy tại sao nó lại đưa ra lỗi phạm vi. nó có thể hữu ích, nhưng nó đã giải quyết vấn đề của tôi
Adnan

115

Đây là một lỗi phổ biến mà mọi người gặp phải khi sử dụng Entity Framework. Điều này xảy ra khi thực thể được liên kết với bảng được lưu có trường thời gian bắt buộc và bạn không đặt nó với một số giá trị.

Đối tượng datetime mặc định được tạo với giá trị là 01/01/1000và sẽ được sử dụng thay cho null. Điều này sẽ được gửi đến cột datetime có thể giữ các giá trị ngày từ 1753-01-01 00:00:00trở đi, nhưng không phải trước đó, dẫn đến ngoại lệ ngoài phạm vi.

Lỗi này có thể được giải quyết bằng cách sửa đổi trường cơ sở dữ liệu để chấp nhận null hoặc bằng cách khởi tạo trường có giá trị.


3
Điều này xảy ra khi trường datetime trong cơ sở dữ liệu là tùy chọn và giá trị không được đặt. Do đó, đây không phải là lỗi phổ biến của mọi người, đây là một trong những vấn đề kiến ​​trúc của EF.
Tư vấn GSoft

1
Tôi đồng ý EF sẽ thấy loại trong DB và điều chỉnh cho phù hợp hoặc ném hoặc ít nhất là ném một lỗi chính xác hơn. Mặt khác, tôi thích câu trả lời của bạn vì bạn đã cung cấp 2 tùy chọn thay vì lựa chọn thông thường - khởi tạo tệp được gửi với giá trị tối thiểu.
DanteTheSmith

43

DATETIMEhỗ trợ 1753/1/1 đến "vĩnh cửu" (9999/12/31), trong khi DATETIME2hỗ trợ 0001/1/1 đến vĩnh cửu.

Trả lời: Tôi cho rằng bạn cố gắng lưu DateTimevới giá trị '0001/1/1'. Chỉ cần đặt điểm dừng và gỡ lỗi nó, nếu vậy thì thay thế DateTimebằng nullhoặc đặt ngày bình thường.


Tôi phải làm gì trong Bộ điều khiển? Gỡ lỗi chỉ mang đến lỗi mà tôi đã đăng ở trên. Cảm ơn.
Cameron

có vẻ như lỗi ở đây -> _db.SaveChanges (); Bạn có thể đặt điểm dừng trước dòng này ...
Andrew Orsich

Vâng đã làm. Sau đó, nó nói rằng đó là một lỗi trên SaveChanges vì ​​vậy tôi nhìn vào InternalException và nó nói rằng đó là do lỗi được đăng nên đó là lỗi!
Cameron

Bạn đã kiểm tra giá trị DateTime trước _db.SaveChanges (); được gọi là? Nó sẽ tuyệt vời hơn '1753/1/1'.
Andrew Orsich

Giá trị ngày gốcArticle là {18/10/2009 00:00:00} và giá trị ngày ArticleToEdit là {01/01/0001 00:00:00} vì vậy có vẻ như nó đang cố gắng thay đổi ngày thành 1 của mọi thứ không phải là Tôi không muốn nhưng tôi không giải thích tại sao nó lại xuất hiện lỗi vì định dạng giống nhau phải không?
Cameron

14

Điều này đã khiến tôi phát điên. Tôi muốn tránh sử dụng thời gian ngày nullable ( DateTime?). Tôi cũng không có tùy chọn sử dụng kiểu datetime2 của SQL 2008 ( modelBuilder.Entity<MyEntity>().Property(e => e.MyDateColumn).HasColumnType("datetime2");).

Cuối cùng tôi đã chọn cho những điều sau đây:

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

Bạn cũng có thể khắc phục sự cố này bằng cách thêm vào mô hình (phiên bản Entity Framework> = 5)

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

8

Nếu bạn có một cột là datetime và cho phép null, bạn sẽ gặp lỗi này. Tôi khuyên bạn nên đặt một giá trị để truyền cho đối tượng trước .SaveChanges ();


5

Tôi đã gặp lỗi này sau khi tôi thay đổi mô hình của mình (mã đầu tiên) như sau:

public DateTime? DateCreated

đến

public DateTime DateCreated

Các hàng hiện tại có giá trị null trong DateCreated gây ra lỗi này. Vì vậy, tôi đã phải sử dụng SQL UPDATE Statement theo cách thủ công để khởi tạo trường với giá trị tiêu chuẩn.

Một giải pháp khác có thể là chỉ định giá trị mặc định cho tệp.


3

Trong trường hợp của tôi, trong trình khởi tạo từ lớp tôi đang sử dụng trong bảng của cơ sở dữ liệu, tôi đã không đặt bất kỳ giá trị mặc định nào cho thuộc tính DateTime của mình, do đó dẫn đến sự cố được giải thích trong câu trả lời của @Andrew Orsich. Vì vậy, tôi chỉ làm cho tài sản vô giá trị. Hoặc tôi cũng có thể đã cho nó DateTime. Bây giờ trong hàm tạo. Hy vọng nó sẽ giúp được ai đó.


3

Có vẻ như bạn đang sử dụng khung thực thể. Giải pháp của tôi là chuyển tất cả các cột datetime sang datetime2 và sử dụng datetime2 cho bất kỳ cột mới nào, nói cách khác là làm cho EF sử dụng datetime2 theo mặc định. Thêm phần này vào phương thức OnModelCreating trong ngữ cảnh của bạn:

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

Điều đó sẽ nhận được tất cả DateTime và DateTime? thuộc tính trên tất cả các thực thể trong mô hình của bạn.


2

Tôi gặp vấn đề tương tự, thật không may, tôi có hai thuộc tính DateTime trên mô hình của mình và một thuộc tính DateTime là null trước khi tôi thực hiện SaveChanges.

Vì vậy, hãy đảm bảo mô hình của bạn có giá trị DateTime trước khi lưu các thay đổi hoặc làm cho nó không thể thực hiện được để tránh lỗi:

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

Vì vậy, điều này giải quyết vấn đề của tôi, vấn đề là đảm bảo ngày mô hình của bạn là chính xác trước khi tiếp tục cơ sở dữ liệu:

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

2

Nếu bạn đang sử dụng phiên bản Entity Framework> = 5 thì áp dụng chú thích [DatabaseGenerated (DatabaseGeneratedOption.Computing)] cho các thuộc tính DateTime của lớp bạn sẽ cho phép trình kích hoạt của bảng cơ sở dữ liệu thực hiện công việc nhập ngày để tạo bản ghi và cập nhật bản ghi mà không gây ra mã Entity Framework của bạn để bịt miệng.

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

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

Điều này tương tự như câu trả lời thứ 6, được viết bởi Dongolo Jeno và Edited bởi Gille Q.


1

Ngoài ra, nếu bạn không biết một phần mã xảy ra lỗi, bạn có thể cấu hình thực thi sql "xấu" bằng cách sử dụng profiler profl được tích hợp vào mssql.

Thông số thời gian xấu sẽ hiển thị một cái gì đó như thế:

thông số xấu


1

Vấn đề này thường xảy ra khi bạn đang cố cập nhật một thực thể. Ví dụ: bạn có một thực thể chứa trường được gọi DateCreated[Bắt buộc] và khi bạn chèn bản ghi, không có lỗi nào được trả về nhưng khi bạn muốn Cập nhật thực thể cụ thể đó, bạn sẽ nhận được

chuyển đổi datetime2 ra khỏi phạm vi lỗi.

Bây giờ đây là giải pháp:

Trên chế độ xem chỉnh sửa của bạn, tức là edit.cshtmlđối với người dùng MVC, tất cả những gì bạn cần làm là thêm trường biểu mẫu ẩn cho bạn DateCreatedngay bên dưới trường ẩn cho khóa chính của dữ liệu chỉnh sửa.

Thí dụ:

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

Thêm phần này vào chế độ xem chỉnh sửa của bạn, bạn sẽ không bao giờ gặp phải lỗi đó. Tôi đảm bảo với bạn.


1

Bạn phải bật giá trị null cho biến ngày của mình:

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

0

Hãy thử làm cho tài sản của bạn vô giá trị.

    public DateTime? Time{ get; set; }

Đã làm cho tôi.


0

Nếu bạn đã truy cập vào DB, bạn có thể thay đổi loại cột DB từ datetime thành datetime2 (7) nó sẽ vẫn gửi một đối tượng datetime và nó sẽ được lưu


0

Mô hình nên có datetime nullable. Phương thức được đề xuất trước đó để truy xuất đối tượng phải được sửa đổi nên được sử dụng thay vì ApplyPropertyChanges. Trong trường hợp của tôi, tôi đã có phương pháp này để Lưu đối tượng của mình:

public ActionResult Save(QCFeedbackViewModel item)

Và sau đó trong dịch vụ, tôi truy xuất bằng cách sử dụng:

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

Mã đầy đủ của dịch vụ như sau:

 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

[Đã giải quyết] Trong Mã khung thực thể Đầu tiên (trường hợp của tôi) chỉ cần thay đổi DateTimeđể DateTime?giải quyết vấn đề của tôi.

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

0

Lỗi: Việc chuyển đổi loại dữ liệu datetime2 thành loại dữ liệu datetime dẫn đến giá trị ngoài phạm vi.

Lỗi này xảy ra khi do KHÔNG gán bất kỳ giá trị nào cho cột ngày KHÔNG NULL trong SQL DB bằng cách sử dụng EF và đã được giải quyết bằng cách gán tương tự.

Hi vọng điêu nay co ich!


0

Có vấn đề này khi tạo các lớp của tôi từ cách tiếp cận cơ sở dữ liệu đầu tiên. Được giải quyết bằng cách sử dụng đơn giản Convert.DateTime (dateCausingPro Hiệu) Trong thực tế, luôn cố gắng chuyển đổi giá trị trước khi vượt qua, Nó giúp bạn tiết kiệm từ các giá trị không mong muốn.


0

bạn phải khớp định dạng đầu vào của trường ngày của bạn với định dạng thực thể bắt buộc là yyyy / mm / dd


1
Có những câu trả lời khác cung cấp câu hỏi của OP và chúng đã được đăng cách đây một thời gian. Khi đăng một câu trả lời xem: Làm thế nào để tôi viết một câu trả lời tốt? , vui lòng đảm bảo bạn thêm một giải pháp mới hoặc giải thích rõ ràng hơn, đặc biệt là khi trả lời các câu hỏi cũ hơn.
help-info.de
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.