2009-02-13 56 views
7

Bảng của tôi có cột dấu thời gian có tên "RowVer" mà LINQ ánh xạ để nhập System.Data.Linq.Binary. kiểu dữ liệu này có vẻ vô ích với tôi bởi vì (trừ khi tôi đang thiếu một cái gì đó) tôi không thể làm những việc như thế này:Truy vấn cột dấu thời gian từ LINQ to SQL

// Select all records that changed since the last time we inserted/updated. 
IEnumerable<UserSession> rows = db.UserSessions.Where 
(usr => usr.RowVer > ????); 

Vì vậy, một trong những giải pháp tôi đang nhìn vào là thêm một mới "tính cột" gọi RowTrack được định nghĩa trong SQL như thế này:

CREATE TABLE UserSession 
(
RowVer timestamp NOT NULL, 
RowTrack AS (convert(bigint,[RowVer])), 
-- ... other columns ... 
) 

này cho phép tôi để truy vấn cơ sở dữ liệu như tôi muốn:

// Select all records that changed since the last time we inserted/updated. 
IEnumerable<UserSession> rows = db.UserSessions.Where 
(usr => usr.RowTrack > 123456); 

Đây có phải là một cách xấu để làm những việc? Cách người thực hiện truy vấn trên cột được tính toán? Có công việc tốt hơn không?

Ngoài ra, tôi đang phát triển chống lại Sql Server 2000 cho khả năng tương thích ngược tối hậu, nhưng tôi có thể nói với ông chủ làm năm 2005 mẫu số chung thấp nhất.

Trả lời

4

// Chọn tất cả các bản ghi đã thay đổi kể từ lần cuối cùng chúng tôi chèn/cập nhật.

Có hoạt động tốt hơn không?

Tại sao không có hai cột, một cột để tạo ngày khác cho lastmodifieddate. Tôi sẽ nói đó là cách truyền thống hơn để xử lý kịch bản này.

+0

Cảm ơn bài đăng của bạn. Nó làm cho tôi nghĩ về vấn đề hơn nữa để nhận ra rằng một datetime là tốt hơn nhiều bởi vì nó đại diện cho một mảnh thông tin hữu ích hơn. Bây giờ tôi có thể phát hiện _how_ cũ một bản ghi là, không chỉ nếu nó cũ. –

+0

đừng quên thêm chỉ mục cho chúng –

6

Dấu thời gian SQL Server "" chỉ là một chỉ báo cho thấy bản ghi đã thay đổi, nó không thực sự là biểu diễn của Ngày/Giờ. (Mặc dù giả sử tăng dần mỗi lần một bản ghi trong DB được sửa đổi,

Hãy coi chừng nó sẽ bị trả về 0 (không thường xuyên, thừa nhận), do đó, kiểm tra an toàn duy nhất là nếu giá trị đã thay đổi, không Nếu nó lớn hơn giá trị trước đó một số tùy ý

Bạn có thể chuyển giá trị cột TimeStamp vào biểu mẫu web, sau đó khi nó được gửi xem TimeStamp từ biểu mẫu có khác với giá trị trong bản ghi hiện tại không - một người khác đã thay đổi & đã lưu bản ghi trong thời gian tạm thời.

+0

nếu bạn chỉ cần kiểm tra nếu giá trị đã thay đổi, bạn có thể so sánh các trường hợp nhị phân với "a == b" – Lucas

+0

Cảm ơn bài đăng của bạn. Bây giờ tôi có một sự hiểu biết tốt hơn về lý do tại sao tôi không nên cố gắng tái mục đích cột RowVer của tôi. –

+1

Trên thực tế, cột dấu thời gian là khá thiết thực cho mục đích này. Bạn không cần phải lo lắng về nó gói, trừ khi bạn đang thực hiện nhiều hơn 2^64 sửa đổi cho một bảng duy nhất. Để tham khảo, điều đó sẽ mất gần 600.000 năm với 1.000.000 lần mỗi giây. – Josh

8

AS Diego Frata phác thảo trong this post có một hack t mũ cho phép timestamps có thể truy vấn được từ LINQ.

Bí quyết là để xác định một Hãy so sánh phương pháp mà phải mất hai System.Data.Linq.Binary thông số

public static class BinaryComparer 
{ 
public static int Compare(this Binary b1, Binary b2) 
{ 
throw new NotImplementedException(); 
} 
} 

Chú ý rằng các chức năng không cần phải được thực hiện, chỉ có tên của nó (So sánh) là điều quan trọng.

Và truy vấn sẽ giống như thế:

Binary lastTimestamp = GetTimeStamp(); 
var result = from job in c.GetTable<tblJobs> 
      where BinaryComparer.Compare(job.TimeStamp, lastTimestamp)>0 
      select job; 

(này trong trường hợp công việc.Nhãn thời gian> lastTimestamp)

EDIT: Xem Rory MacLeod's answer cho một thực hiện của phương pháp này, nếu bạn cần nó để làm việc bên ngoài của SQL.

+0

Cũng hoạt động trong Entity Framework (4.3.1), sử dụng Byte [] thay vì Binary để so sánh. –

+0

Các liên kết đến hồ sơ và blog của Diego không còn hoạt động nữa. –

2

Tiếp theo từ jaraics' answer, bạn cũng có thể cung cấp một thực hiện đối với phương pháp Compare mà sẽ cho phép nó hoạt động bên ngoài của một truy vấn:

public static class BinaryExtensions 
{ 
    public static int Compare(this Binary b1, Binary b2) 
    { 
     if (b1 == null) 
      return b2 == null ? 0 : -1; 

     if (b2 == null) 
      return 1; 

     byte[] bytes1 = b1.ToArray(); 
     byte[] bytes2 = b2.ToArray(); 
     int len = Math.Min(bytes1.Length, bytes2.Length); 
     int result = memcmp(bytes1, bytes2, len); 

     if (result == 0 && bytes1.Length != bytes2.Length) 
     { 
      return bytes1.Length > bytes2.Length ? 1 : -1; 
     } 

     return result; 
    } 

    [DllImport("msvcrt.dll")] 
    private static extern int memcmp(byte[] arr1, byte[] arr2, int cnt); 
} 

Việc sử dụng memcmp được lấy từ this answer đến một câu hỏi về so sánh mảng byte. Nếu các mảng không có cùng độ dài, nhưng mảng dài hơn bắt đầu bằng cùng một byte với mảng ngắn hơn, mảng dài hơn được coi là lớn hơn mảng ngắn hơn, ngay cả khi các byte thừa là tất cả các số không.

Các vấn đề liên quan