2013-04-17 46 views
8

Tôi có một truy vấn với cách datetimes được so sánh/lưu trữ trong C#. Hãy xem xét mã sau:So sánh datetimes bằng không so sánh

var createdDate = DateTime.Now; 
using (cr = new LanguageDictionaryRepository(ds)) { 
    cr.Add(new Sybrin10.Data.DTO.LanguageDictionary() { 
     Active = true, 
     CreatedDate = createdDate, 
     CultureCode = cultureCode, 
     Data = new System.Text.UTF8Encoding().GetBytes("Test") 
    }); 
    cr.Save(); 

    var y = cr.FindBy(x => x.CultureCode == cultureCode && x.CreatedDate == createdDate).FirstOrDefault(); 
    Assert.IsNotNull(y); 

Assert.IsNotNull không thực hiện được do kiểm tra ngày giờ. Tôi hy vọng rằng khi cá thể LanguageDictionary được tạo ra với giá trị của biến đó, hai giá trị này sẽ bằng nhau. Điều này đang sử dụng Telerik.OpenAccess và MSSQL như là một lớp DB vì vậy tôi giả định vấn đề đi kèm trong đó. Bất cứ ai có thể cho tôi biết nếu có bất cứ điều gì tôi đang thiếu với điều này và làm thế nào để so sánh chính xác các giá trị này.

EDIT: Các giá trị đánh dấu là khác nhau nhưng tôi không biết tại sao như cả hai đều xuất phát từ cùng một biến mà tôi chỉ gán cho một lần.

+1

Bạn có chắc chắn những ngày giống hệt nhau? Việc so sánh sẽ mất vài giờ/phút/giây/milli giây trong tài khoản. – Oded

+0

Đó là điều, các giá trị đánh dấu là khác nhau nhưng tôi không chắc chắn lý do tại sao khi cả hai đều xuất phát từ CreatedDate biến tương tự. – Ash

+0

System.DateTime – Ash

Trả lời

15

Hãy thử sử dụng DateTime.Equals(x.CreatedDate, createdDate), nó có thể giúp đỡ.

Khác với điều đó, thích hợp DateTime so sánh là một chủ đề phức tạp ồ ạt với múi giờ, bù trừ, utc, giờ địa phương và không có điều gì. Tôi sẽ không được ngạc nhiên tại một đơn giản == so sánh giữa hai ngày dường như giống hệt nhau để trả về false.

Nếu giá trị Ticks khác với viết và đọc, bạn có thể gặp phải sự cố DateTimeKind, nơi bạn đang viết DateTimeKind.Local vào cơ sở dữ liệu, nhưng nhận lại DateTimeKind.Unspecified.

Các tùy chọn khác có thể (nếu sự khác biệt là đủ nhỏ) mà DateTime lĩnh vực trong cơ sở dữ liệu của bạn là không đáng kể, đủ để lưu trữ cùng một lượng mili giây như .net DateTime:

Một đánh dấu đơn đại diện cho một trăm nano giây hoặc một phần mười phần triệu giây. Có 10.000 ve trong một phần nghìn giây.

Tùy thuộc vào lưu trữ dữ liệu của bạn, nó có thể không được chi tiết như thế này. Giá trị DateTime của bạn không đến từ cùng một nguồn, một giá trị được đọc từ bộ nhớ, giá trị còn lại được đọc từ cơ sở dữ liệu.

+0

Cảm ơn ý tưởng nhưng điều đó cũng không hiệu quả. – Ash

+0

Trong trường hợp đó, việc so sánh biểu diễn chuỗi ngày tháng là một tùy chọn hợp lệ? – Ash

+0

Nếu bạn chỉ muốn lấy lại bản ghi mà bạn đã tạo, hãy xem Telerik [Làm thế nào để: Chèn đối tượng] (http://www.telerik.com/help/openaccess-orm/developer-guide-crud-add.html). Nó sẽ đọc lại khóa chính đã tạo sau khi lưu. –

0

Tôi nghĩ bạn nên sử dụng DateTime.UtcNow khi bạn lưu trữ dữ liệu và sau đó bạn không phải lo lắng về vấn đề thời gian tiết kiệm ánh sáng ban ngày, v.v. bạn chọn.

+0

Điều đó không hiệu quả. – Ash

2

cửa hàng SQLServer một datetime trong từng bước 3-phần nghìn giây (khoảng).

giá trị datetime được làm tròn đến số gia của 0,000, 0,003, hoặc 0,007 giây

đón tới một DateTime thông qua cơ sở dữ liệu như vậy có thể được tắt bằng một vài ms.

Vì vậy, bạn không nên kiểm tra "chính xác bằng", nhưng đối với "đủ gần"

var y = cr.FindBy(x => x.CultureCode == cultureCode && 
        x.CreatedDate >= createdDate.AddMilliseconds(-5) && 
        x.CreatedDate <= createdDate.AddMilliseconds(5)) 
    .FirstOrDefault(); 
+0

Tôi không biết điều này, cảm ơn đã chỉ ra nó, tôi muốn upvote nhưng mẫu mã của bạn không phải là rất thực tế trong thực tế. bây giờ nếu bạn làm cho nó một phần mở rộng, bây giờ chúng tôi đang nói –

+0

Bạn có thể sử dụng '(x.CreatedDate - createdDate) .Milliseconds <4' nếu bạn đang tìm kiếm một ký hiệu ngắn hơn. – DdW

+2

@DdW - Bạn sẽ cần phải thêm một 'Math.Abs' xung quanh nó, bởi vì bạn có thể nhận được giá trị âm từ so sánh đó (tất nhiên là luôn luôn <4) –