查询从LINQ到SQL的时间戳列

时间:2009-02-13 21:08:26

标签: sql-server linq performance

我的表有一个名为“RowVer”的时间戳列,LINQ映射到System.Data.Linq.Binary类型。这种数据类型对我来说似乎没用,因为(除非我遗漏了什么)我不能做这样的事情:

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

因此,我正在研究的解决方案之一是添加一个名为RowTrack的新“计算列”,它在SQL中定义如下:

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

这允许我像我想要的那样查询数据库:

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

这是一种糟糕的做事方式吗?查询计算列的性能如何?有更好的解决方法吗?

另外,我正在针对Sql Server 2000进行开发以获得最终的向后兼容性,但我可以与老板谈论使2005年成为最低的共同点。

4 个答案:

答案 0 :(得分:9)

Diego Frata中,

AS this post概述了一个hack,它允许从LINQ查询时间戳。

诀窍是定义一个比较方法,该方法需要两个 System.Data.Linq.Binary 参数

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

请注意,该功能不需要实现,只有它的名称(比较)很重要。

查询看起来像:

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

(这是在job.TimeStamp&gt; lastTimestamp的情况下)

修改: 如果您需要在SQL之外工作,请参阅Rory MacLeod's answer以获取该方法的实现。

答案 1 :(得分:6)

SQL Server“timestamp”只是记录已更改的指示符,它实际上并不表示日期/时间。 (虽然每次修改数据库中的记录时都会增加,但

请注意它将回绕到零(通常不是经常),所以唯一安全的测试是,如果值已经改变,而不是大于某个任意的先前值。

您可以将TimeStamp列值传递给Web表单,然后在提交时查看表单中的TimeStamp是否与当前记录中的值不同 - 如果它不同,则其他人已更改&amp;在过渡期间保存了记录。

答案 2 :(得分:4)

  
    

//选择自上次插入/更新以来更改的所有记录。

         

有更好的解决方法吗?

  

为什么不有两列,一列用于lastdifieddate的createddate另一列。我想说这是处理这种情况的更传统方式。

答案 3 :(得分:2)

jaraics' answer开始,您还可以提供Compare方法的实现,以允许它在查询之外工作:

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

使用memcmpthis answer获取有关比较字节数组的问题。如果数组长度不同,但较长的数组以与较短数组相同的字节开始,则较长的数组被认为大于较短的数组,即使额外的字节都是零。