Tip Rápido: Obtener Valor Identity Disponible

Definición del Problema

Dada una tabla de Base de datos con un campo auto numérico, es decir, Identity en Sql Server, el valor no se puede repetir a no ser que eliminemos el registro, y forcemos a que se reinicie en un momento dado, y luego ….

El problema que quiero definir es como obtener los saltos existentes, es decir, aquellos que han sido borrados.

Solución

Como LINQ es algo que me encanta voy a proponer una solución utilizando LINQ:

 

Imaginemos un conjunto de registros cuyo campo Identity presenta estos valores: 1,2,3,5,6,7,9,10,11,15.

 

Para simplificar el ejemplo, voy a definir los en una lista:

   1: List<int> listado = new List<int>();

   2: listado.AddRange(new []{1,2,3,5,6,7,9,11,15});

En principio vamos a realizar una consulta sobre la lista/array/EntitySet… como la siguiente:

 

   1: var query = from n in listado

   2:             where (n!=1 && (!listado.Contains(n-1)))

   3:             select listado.IndexOf(n);

Con esto vamos a obtener los saltos existentes: 5,9,11,15

Al ir a realizar una inserción nos bastaría con obtener el primero de ellos, por lo tanto usaremos el siguiente fragmento:

   1: int numero = query.FirstOrDefault() + 1;

Espero que os sirva.

 

Saludos

Edit: Después del comentario de Santiago, he pensado una solución más rápida digamos. En principio, las posiciones de cada elemento de la lista deben corresponder con el valor de su indice – 1, si no es así significaría que tenemos un salto:

 

 

   1: var query = from n in listado

   2:               where (n > 1 && (listado.IndexOf(n)!=n-1))

   3:               select listado.IndexOf(n);

3 comentarios en “Tip Rápido: Obtener Valor Identity Disponible”

  1. Interesante el problema, y la solución funciona sin lugar a dudas, pero hay un pequeño detalle que hay que tener en cuenta cuando tenemos que aplicar algo como esto en un problema real: En dependencia de la cantidad de registros que tenga la tabla, la búsqueda del primer salto puede tornarse extremadamente lenta utilizando la solución que propones.

    El método Contains no tiene conocimiento de la naturaleza de los datos, por lo que el costo del algoritmo es de O(n) = n. Esto quiere decir que siempre el método Contains tendrá que analizar todos los registros de la tabla en caso que no exista ningún salto. Obviamente, con tablas medianamente grandes, el costo en tiempo será inaceptable.

    En el ejemplo específico que planteas, los elementos van a estar siempre ordenados por el ID. Es por ese mismo campo donde vas a hacer la búsqueda, así que solo bastaría retornar el elemento “n” cuyo vecino más cercano “n+1” no sea el valor consecutivo. Algo así:

    Resultado = E(n) cuando E(n+1) != E(n) – 1

    Un poco abstracto, pero espero que entiendas mi idea.

    Un saludo.

  2. Gracias por el comentario Santiago, creo que la solución que he planteado ahora en el Edit, es más correcta, aunque todavía estoy pensando en posibles alternativas.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *