statements for condiciones commands sql-server linq performance

sql-server - for - where condition sql server



Consultar una columna de marca de tiempo de LINQ a SQL (4)

// Seleccione todos los registros que cambiaron desde la última vez que insertamos / actualizamos.

¿Hay una mejor solución?

¿Por qué no tener dos columnas, una para fecha de creación y otra para fecha de última modificación? Yo diría que es la forma más tradicional de manejar este escenario.

Mi tabla tiene una columna de marca de tiempo llamada "RowVer" que LINQ correlaciona para escribir System.Data.Linq.Binary. Este tipo de datos me parece inútil porque (a menos que me falta algo) no puedo hacer cosas como esta:

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

Entonces, una de las soluciones que estoy buscando es agregar una nueva "columna calculada" llamada RowTrack que se define en SQL de esta manera:

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

Esto me permite consultar la base de datos como quiero:

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

¿Es esta una mala forma de hacer las cosas? ¿Qué rendimiento está consultando en una columna calculada? ¿Hay una mejor solución?

Además, me estoy desarrollando contra Sql Server 2000 para la última compatibilidad con versiones anteriores, pero puedo convencer al jefe para que haga de 2005 el denominador común más bajo.


La "marca de tiempo" de SQL Server es solo un indicador de que el registro ha cambiado, en realidad no es una representación de Fecha / Hora. (Aunque se supone que debe incrementarse cada vez que se modifica un registro en el DB,

Tenga en cuenta que volverá a cero (no muy a menudo, es cierto), por lo que la única prueba segura es si el valor ha cambiado, no si es mayor que algún valor anterior arbitrario.

Puede pasar el valor de la columna TimeStamp a un formulario web, y luego, cuando se envía, ver si el TimeStamp del formulario es diferente del valor en el registro actual; si es diferente, alguien más ha cambiado y guardado el registro en el interino. .


A partir de la respuesta de jaraics , también podría proporcionar una implementación para el método de Compare que le permitiría trabajar fuera de una consulta:

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

El uso de memcmp se tomó de esta respuesta a una pregunta sobre la comparación de matrices de bytes. Si las matrices no tienen la misma longitud, pero la matriz más larga comienza con los mismos bytes que la matriz más corta, la matriz más larga se considera que es mayor que la más corta, incluso si los bytes adicionales son todos ceros.


Como señala Diego Frata en esta publicación, hay un truco que permite que las marcas de tiempo sean consultables desde LINQ.

El truco es definir un método de comparación que tome dos parámetros System.Data.Linq.Binary

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

Tenga en cuenta que la función no necesita implementarse, solo su nombre ( Comparar ) es importante.

Y la consulta se verá algo así como:

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

(Esto en el caso de job.TimeStamp> lastTimestamp)

EDITAR : Consulte la respuesta de Rory MacLeod para una implementación del método, si necesita que funcione fuera de SQL.