Chuyển đổi loại dữ liệu datetime2 thành loại dữ liệu datetime mang lại giá trị ngoài phạm vi


379

Tôi đã có một dữ liệu với 5 cột, trong đó một hàng đang được điền dữ liệu sau đó được lưu vào cơ sở dữ liệu thông qua một giao dịch.

Trong khi lưu, một lỗi được trả về:

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

Như đã đọc, nó có nghĩa là DateTime2dữ liệu của tôi có một loại và cơ sở dữ liệu của tôi a DateTime; đó là sai

Cột ngày được đặt thành DateTimenhư thế này:

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

Câu hỏi

Điều này có thể được giải quyết trong mã hoặc một cái gì đó phải được thay đổi ở cấp độ cơ sở dữ liệu?

Câu trả lời:


60

Những loại ngày bạn có trong cột?

Có phải tất cả trong số họ phù hợp trong phạm vi của các loại?


Bên cạnh đó, cách chính xác để có được một Typeđối tượng cho hàm DataColumntạo là typeoftừ khóa, là thứ tự có độ lớn nhanh hơn.

Do đó, để tạo cột, bạn nên viết

new DataColumn("myDate", typeof(DateTime))

3
Tôi đã thay đổi datacolumn và sử dụng typeof ngay bây giờ ... Hơn nữa tôi đã tìm thấy vấn đề của mình. có 1 datarow chứa một ngày sai, gây ra lỗi
Gerbrand

739

Điều này có thể xảy ra nếu bạn không gán giá trị cho trường DateTime khi trường không chấp nhận giá trị NULL .

Điều đó đã sửa nó cho tôi!


43
Trong Entity Framework, nếu bạn thêm một cột Đã tạo không phải là null, thì hãy cập nhật EDMX của bạn, khi bạn không đặt giá trị trong mã, điều đó có thể gây ra lỗi này theo cách này
Brad Thomas

6
Điều gì đã sửa nó cho bạn? Lỗi này xuất hiện khi bạn có trường datetime với lệnh gọi getdate () làm giá trị mặc định.
3046061

15
Tại sao Khung thực thể không thể bỏ qua nếu NULL vì về phía SQL của tôi, tôi có giá trị mặc định = getdate ()?
JoshYates1980

33
Điều tôi tin rằng nó xảy ra là EntityFramework thấy DateTime.MinValue là năm 0001 và trong datetime SQL nằm ngoài giá trị phạm vi, do đó, nó gửi giá trị này dưới dạng giá trị DateTime2 (hỗ trợ năm 0001), tuy nhiên, chèn / cập nhật là hợp lệ, tuy nhiên nó không thành công khi SQL cố gắng chuyển đổi DateTime2 này thành DateTime vì điều này sẽ dẫn đến một giá trị khác. Hai giải pháp là: 1 Sử dụng một datetime nullable trong mô hình của bạn hoặc 2. khởi tạo tất cả các giá trị datetime của bạn, thành giá trị chính xác trước khi lưu các thay đổi ngữ cảnh. Sự lựa chọn bạn đưa ra phụ thuộc vào ý nghĩa của datetime trong mô hình của bạn.
Guillermo Ruffino

1
Giải pháp của @ GuillermoRuffino đã làm việc cho tôi. Kiểm tra tất cả các lĩnh vực của bạn và tìm các mục 0001 năm.
Francesco B.

158

Cả DATETIMEDATETIME2ánh xạ tới System.DateTime.NET - bạn thực sự không thể thực hiện "chuyển đổi", vì nó thực sự cùng loại .NET.

Xem trang tài liệu MSDN: http://msdn.microsoft.com/en-us/l Library / bb675168.aspx

Có hai giá trị khác nhau cho " SqlDbType" cho hai giá trị này - bạn có thể chỉ định các giá trị trong DataColumnđịnh nghĩa của mình không?

NHƯNG: trên SQL Server, phạm vi ngày được hỗ trợ khá khác nhau.

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.

Vì vậy, những gì bạn thực sự cần làm là kiểm tra năm của ngày - nếu trước năm 1753, bạn cần thay đổi nó thành một cái gì đó SAU 1753 để DATETIMEcột trong SQL Server xử lý nó.

Marc


7
Điều này giải thích vấn đề mà tôi đã có. Mặc dù có rất ít tình huống cần xử lý ngày thực trước 1753/1/1, nhưng có nhiều tình huống người ta nhận được giá trị mặc định 0001/1/1 có thể dẫn đến lỗi.
Hồng

Tôi xác nhận rằng khi tôi đang cố gắng chèn 'DateTime ()' mới vào loại dữ liệu 'datetime', tôi đã nhận được ngoại lệ này.
George Onofrei

1
Tôi đã cố gắng gán giá trị mặc định của DateTime.MinValue trong mã C # của tôi đã ghi vào cơ sở dữ liệu. Điều này giải thích lỗi tôi đã nhận được. +1
Mkalafut

Tôi sử dụng Entity Framework Code First và tôi sử dụng mô hình với thuộc tính DateTime. DtInit = new System.DateTime(1492, 10, 12),thất bại
Kiquenet

Đây là một trong những tình huống mà lý do thực sự được ẩn giấu sau bản vá ... +1
Eugenio Miró

41

Trong cơ sở dữ liệu SQL Server 2008 của tôi, tôi có một DateTimecột được gắn cờ là không thể rỗng, nhưng với GetDate()chức năng là giá trị mặc định của nó. Khi chèn đối tượng mới bằng EF4, tôi đã gặp lỗi này vì tôi đã không chuyển một thuộc tính DateTime trên đối tượng của mình một cách rõ ràng. Tôi đã mong đợi hàm SQL sẽ xử lý ngày cho tôi nhưng không được. Giải pháp của tôi là gửi giá trị ngày từ mã thay vì dựa vào cơ sở dữ liệu để tạo ra nó.

obj.DateProperty = DateTime.now; // C#

2
Vui mừng được giúp đỡ. Thật khó chịu vì bạn nghĩ bối cảnh dữ liệu của EF sẽ có thể phát hiện ra rằng trường có giá trị mặc định khi đối tượng được tạo từ bảng.
Graham

Tôi đã nghĩ rất nhiều điều về EF. Tôi đang sử dụng các thực thể tự theo dõi POCO và nó là một cụm như vậy. Tôi sẽ kiểm tra mô hình mã đầu tiên, và nếu nó cũng vô nghĩa, tôi nghiêm túc suy nghĩ về việc quay lại linq sang sql và sử dụng một trình ánh xạ đối tượng để ánh xạ đạo cụ đến các thực thể của riêng tôi ...

2
Tôi đã xem bản demo của Mã EF đầu tiên tại VS Live 2 tuần trước và nó trông TUYỆT VỜI, btw.
Graham

Đó là tin tốt. Chúng tôi sẽ sớm bắt đầu một dự án mới tại văn phòng của mình và tôi đã chia ra EF-CF và dapper (được sử dụng / duy trì bởi SO). Nó có thể sẽ đi xuống cái nào tốt hơn trong một ứng dụng được sử dụng thông qua dịch vụ WCF.

1
Xin chào, ý kiến ​​tuổi! Bản thân tôi đang bắt đầu với EF Code-First và thấy rằng trên POCO của mình, tôi chỉ cần xác định thành viên datetime của mình là Nullable<DateTime>, và trong mã tôi có thể để nó thực sự không có giá trị (thay vì 01/01/0000). Tôi đã rất ngạc nhiên khi thấy rằng EF to SQL đã biết bỏ qua null này trên INSERT và sử dụng ngày từ máy chủ (GetDate() ) ... Đối với chúng tôi, điều này thậm chí còn tốt hơn vì chúng tôi cần sự nhất quán tốt hơn trên máy chủ, mà không phải lo lắng về sự khác biệt giữa đồng hồ giữa máy chủ web và máy chủ sql.
Funka

34

đối với tôi đó là vì thời gian là ..

01/01/0001 00:00:00

trong trường hợp này, bạn muốn gán null cho đối tượng EF DateTime ... sử dụng mã FirstYearRegistered của tôi làm ví dụ

DateTime FirstYearRegistered = Convert.ToDateTime(Collection["FirstYearRegistered"]);
if (FirstYearRegistered != DateTime.MinValue)
{
    vehicleData.DateFirstReg = FirstYearRegistered;
}  

Tôi đang phân tích dữ liệu này bằng ExcelDataReader và nó sẽ trả về 01/01/0001 khi văn bản không hợp lệ được nhập (không ném ngoại lệ như mong đợi - sử dụng phương thức .GetDateTime (cột Index)). Việc so sánh với MinValue đã thực hiện thủ thuật để ngăn chặn ngoại lệ trong phạm vi sql.
Tommy

22

Đ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 không có tùy chọn sử dụng SQL Server 2008 của datetime2loại hoặc

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

1
Sử dụng [Column(TypeName = "datetime2")]?
Kiquenet

21

Đôi khi, EF không biết rằng đang xử lý một cột được tính toán hoặc kích hoạt . Theo thiết kế, các hoạt động đó sẽ đặt giá trị bên ngoài EF sau khi chèn.

Cách khắc phục là chỉ định Computedtrong EF edmxcho cột đó trongStoreGeneratedPattern tính.

Đối với tôi, đó là khi cột có một trình kích hoạt chèn ngày và giờ hiện tại, xem bên dưới trong phần thứ ba.


Các bước để giải quyết

Trong Visual Studio mở Model Browsertrang sau Modelđó Entity Types-> sau đó

  1. Chọn thực thể và thuộc tính thời gian ngày
  2. Lựa chọn StoreGeneratedPattern
  3. Đặt thành Computed

Hộp thoại Kiểu thực thể Mô hình Trình duyệt EF


Đối với tình huống này, các câu trả lời khác là cách giải quyết, vì mục đích của cột là có thời gian / ngày được chỉ định khi bản ghi được tạo và đó là công việc của SQL để thực thi kích hoạt để thêm thời gian chính xác. Chẳng hạn như trình kích hoạt SQL này:

DEFAULT (GETDATE()) FOR [DateCreated].


Lưu ý rằng tôi đã sử dụng GETDATE()mà tôi thực sự đã làm vào thời điểm đó. Nhưng có một nhận xét gần đây rằng một người nên sử dụng SYSDATETIME()cho bất kỳ hoạt động DateTime2 nào mà tôi tin là đúng.
ΩmegaMan

10

Tôi chạy vào đây và thêm phần sau vào thuộc tính datetime của mình:

 [Column(TypeName = "datetime2")]
 public DateTime? NullableDateTimePropUtc { get; set; }

1
using System.ComponentModel.DataAnnotations.Schema; là bắt buộc
Kiquenet

9

Nếu chúng ta không vượt qua trường thời gian ngày đến ngày thời gian, ngày mặc định {1/1/0001 12:00:00 AM} sẽ được thông qua.

Nhưng ngày này không tương thích với công việc khung thực thể nên nó sẽ ném 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

Chỉ cần default DateTime.nowđến trường ngày nếu bạn không vượt qua bất kỳ ngày nào.

movie.DateAdded = System.DateTime.Now

Tôi sẽ nói việc chuyển 'DateTime.Now' làm giá trị mặc định khác xa so với chính xác và khá sai lệch.
Bartosz

6

Cách dễ nhất là thay đổi cơ sở dữ liệu của bạn để sử dụng datetime2 thay vì datetime. Khả năng tương thích hoạt động tốt và bạn sẽ không gặp phải lỗi của mình.

Bạn vẫn muốn thực hiện một loạt các thử nghiệm ...

Lỗi có thể là do bạn đang cố gắng đặt ngày thành năm 0 hoặc một cái gì đó - nhưng tất cả phụ thuộc vào nơi bạn có quyền kiểm soát để thay đổi công cụ.


4

Tôi tìm thấy bài đăng này cố gắng tìm hiểu lý do tại sao tôi tiếp tục nhận được lỗi sau đây được giải thích bởi các câu trả lời khác.

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.

Sử dụng một đối tượng DateTime nullable.
Ngày giờ công khai? Mua hàng ngày {nhận; bộ; }

Nếu bạn đang sử dụng khung thực thể Đặt thuộc tính nullable trong tệp edmx thành True

Đặt thuộc tính nullable trong tệp edmx thành ** True **


3

Như andyuk đã chỉ ra, điều này có thể xảy ra khi giá trị NULL được gán cho trường DateTime không thể rỗng . Cân nhắc thay đổi DateTime thành DateTime? hoặc Nullable < DateTime >. Xin lưu ý rằng, trong trường hợp bạn đang sử dụng Thuộc tính phụ thuộc , cũng nên đảm bảo rằng loại thuộc tính phụ thuộc của bạn cũng là loại DateTime không thể rỗng.

Dưới đây là một ví dụ thực tế về một DateTime chưa hoàn thành đến DateTime? điều chỉnh kiểu làm tăng hành vi kỳ quặc

nhập mô tả hình ảnh ở đây


2

Entity Framework 4 hoạt động với kiểu dữ liệu datetime2, do đó, trong trường db tương ứng phải là datetime2 cho SQL Server 2008.

Để đạt được giải pháp có hai cách.

  1. Để sử dụng kiểu dữ liệu datetime trong Entity Framwork 4, bạn phải chuyển CarrierManifestToken trong tệp edmx thành "2005".
  2. Nếu bạn đặt trường tương ứng là Cho phép Null (nó chuyển đổi nó thành NULLABLE) thì EF sẽ tự động sử dụng các đối tượng ngày làm datetime.

1
Tôi đã chọn điểm thứ hai của bạn cho các mô hình cơ sở dữ liệu của tôi (các lớp POCO) và tự hỏi làm thế nào để đặt trường thành một loại không thể. Trong trường hợp bất cứ ai thắc mắc, bạn có thể làm điều này bằng cách thêm Dấu hỏi (?) Sau loại ngày. ví dụ DateTime công khai? Thời gian bắt đầu {nhận; bộ; } Điều này đã giải quyết vấn đề cho tôi. Chỉ có một điều khác tôi phải làm là đặt một biểu tượng TimeSpan xung quanh một dòng mã nơi tôi đang trừ hai giá trị DateTime không thể tách rời khỏi nhau. ví dụ: var timeTaken = (TimeSpan) (endTime - startTime);
Ciaran Gallagher

1

Tạo một lớp cơ sở dựa trên việc thực hiện @ sky-dev. Vì vậy, điều này có thể dễ dàng áp dụng cho nhiều bối cảnh và thực thể.

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

Sử dụng:

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.)
 }

1

Thêm thuộc tính được đề cập dưới đây vào thuộc tính trong lớp mô hình của bạn.

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

Ban đầu tôi quên thêm thuộc tính này. Vì vậy, trong cơ sở dữ liệu của tôi, các ràng buộc đã được tạo như

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

và tôi đã thêm thuộc tính này và cập nhật db của tôi sau đó nó đã được thay đổi thành

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

[DatabaseGenerated (DatabaseGeneratedOption.Computing)]
Ajith Chandran

0

Trong trường hợp của tôi, chúng tôi đã chuyển một Ngày thành Ngày và chúng tôi đã gặp lỗi này. Điều gì xảy ra là Ngày có tối thiểu "định hướng lập trình viên nhiều hơn" là 01/01/0001, trong khi Ngày tháng bị kẹt ở 1753

Kết hợp điều đó với một lỗi thu thập dữ liệu từ phía chúng tôi và bạn sẽ có được ngoại lệ của mình!


America Discover vào năm 1492, sai nếu không sử dụng datetime2
Kiquenet

0

Đôi khi nó hoạt động tốt trên các máy phát triển và không phải trong máy chủ. Trong trường hợp của tôi, tôi đã phải đặt:

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

Trong tệp web.config.

Múi giờ trong máy (Máy chủ) đã đúng (với miền địa phương CO) nhưng ứng dụng web thì không. Cài đặt này được thực hiện và nó hoạt động tốt trở lại.

Tất nhiên, tất cả các ngày có giá trị.

: D


0

Thêm mã này vào một lớp trong ASP.NET đã giúp tôi thành công:

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

0

Tôi biết vấn đề này và tất cả các bạn cũng vậy:

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

Trong SQL, một loại trường mới đã được tạo để tránh vấn đề này (datetime2).

Loại trường 'Ngày' này có cùng giá trị phạm vi với lớp DateTime .Net. Nó sẽ giải quyết tất cả các vấn đề của bạn, vì vậy tôi nghĩ cách giải quyết tốt nhất là thay đổi loại cột cơ sở dữ liệu của bạn (nó sẽ không ảnh hưởng đến dữ liệu bảng của bạn).


0

Kiểm tra hai điều sau đây: 1) Trường này không có giá trị NULL. Ví dụ:

 public DateTime MyDate { get; set; }

Thay thế thành:

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

2) Mới cơ sở dữ liệu một lần nữa. Ví dụ:

db=new MyDb();

Nếu bạn không muốn giá trị là DateTime. Theo mặc định thì sao?
Savage

Nếu bạn không muốn: DateTime. Bây giờ. Bạn có thể sử dụng: DateTime mới (..., ..., ...)
RainyTears

0

Sự cố với thuộc tính datetime được kế thừa

Thông báo lỗi này thường được hiển thị khi trường ngày không null có giá trị null tại thời điểm chèn / cập nhật. Một nguyên nhân có thể là thừa kế.

Nếu ngày của bạn được kế thừa từ lớp cơ sở và bạn không tạo bản đồ thì EF sẽ không đọc giá trị của nó.

Để biết thêm thông tin: https://weblogs.asp.net/manavi/inherribution-mapping-strargeties-with-entity-framework-code-first-ctp5-part-3-table-per-concittle-type-tpc-and- lựa chọn chiến lược


0

Tôi đã gặp lỗi này khi tôi muốn chỉnh sửa một trang usnig ASP.Net MVC. Tôi không gặp vấn đề gì trong khi Tạo nhưng Cập nhật Cơ sở dữ liệu khiến thuộc tính DateCreated của tôi nằm ngoài phạm vi!

Khi bạn không muốn DateTimeTài sản của mình là Nullable và không muốn kiểm tra xem giá trị của nó có nằm trong phạm vi DateTime của sql không (và @Html.HiddenForkhông giúp đỡ!), Chỉ cần thêm một static DateTimetrường bên trong lớp liên quan (Trình điều khiển) và cung cấp cho nó giá trị khi GET đang hoạt động sau đó sử dụng nó khi POST đang thực hiện công việc:

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

    }
}

0

Tôi gặp phải vấn đề này trong một dự án ứng dụng bảng điều khiển đơn giản và giải pháp nhanh chóng của tôi là chuyển đổi bất kỳ ngày datetime2 nào có thể thành một datetime nullable bằng cách chạy phương thức này:

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

Đây chắc chắn không phải là một phương pháp hoàn toàn toàn diện, nhưng nó hiệu quả với nhu cầu của tôi và có thể nó sẽ giúp được người khác!


0

Kiểm tra định dạng req trong DB. ví dụ: DB của tôi có giá trị mặc định hoặc liên kết(((1)/(1))/(1900))

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

nhập mô tả hình ảnh ở đây


-1

bạn sẽ có cột ngày được đặt thành lesathan giá trị tối thiểu của thời gian cho phép như 1/1/1001.

để khắc phục vấn đề này, bạn có thể đặt giá trị datetime thích hợp cho thuộc tính ur adn cũng đặt một thuộc tính ma thuật khác như IsSpecified = true.

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.