01 marzo 2006

Recuperar autonumérico generado en un AddNew

Hoy me he embalado. Hemos retomado un tema que teníamos pendiente, la recuperación de valores autonuméricos generados por la base de datos tras añadir un nuevo registro a una tabla. Es necesario usarlo para obtener el Id del objeto, y ADO.net, a diferencia de su hermano chico de VB6, no incorpora la posibilidad de hacerlo. ¿Por qué? Por varias cosas: porque el DataSet está desconectado de la bd y es el DataAdapter el que gestiona esto, porque cada bd tiene un mecanismo distinto para devolver el autonumérico, yo que sé. La cosa es que, aunque esos argumentos no me convencen del todo, el hecho y verdad (que me gusta esta coletilla) es que lo han quitado, y hay que buscarse la vida para obtenerlo manualmente. En el artículo que os enlazo (en el título del artículo) comenta los 2 casos, SQL Server y Access. El de Access es aplicable también a SQL Server (reutilización), pero el de SQL Server es más eficiente por requerir sólo una excursión (roundtrip) a la bd, no 2 como en el método de Access. A pesar de lo cual, la decisión ahora va a ser hacerlo de forma genérica, con el SELECT @@IDENTITY en el evento RowUpdated del DataAdapter. ¿Lo estamos haciendo así actualmente, Carvajal?
Como tenemos que rediseñar la capa de acceso a datos para adaptarnos al tipo (web o bd, y qué tipo concreto de bd), quizá especialicemos la clase para aprovechar mejor SQL Server, pero para eso hay que añadir procedimientos almacenados a la bd, otra pega. De momento lo dicho, la doble arroba y palante.

3 Comments:

Blogger Bernardo said...

Ummm, feo bastante feo. Entonces supuestamente si yo creo 300 lienas en una Table del DataSet, si despues hago un Update me saltará 300 vevces el SELECT @@IDENTITY, una para cada línea. En ese caso sería mejor lo que ya comenté de borrar y volver a cargar la tabla. Generaríamos una sola consulta, a no ser que la consulta SELECT @@IDENTITY sea más eficiente.

01 marzo, 2006 18:09  
Blogger Pablo said...

Es cierto que lanzar 300 SELECT es más ineficiente que recargar la tabla, sobre todo por tráfico de red (que es más importante que vaciar y volver a crear los objetos en memoria). Pero es más sencillo usar una única solución, y que además cubre mejor los casos más probables: crear una colección vacía y añadir una línea, o cargar una colección ya rellena y añadir una línea al final. Volviendo al caso de los 300, también hay que plantearse si se va a aplicar directamente cada objeto en la bd o si se hacen los 300 en bloque. Hacerlo en bloque no es más eficiente, siguen siendo 300 INSERT INTO ... VALUES separados, por lo que intercalar otros 300 SELECT no es ninguna barbaridad. Distinto sería si con una única consulta añadiéramos 300 registros (INSERT INTO ... SELECT) pero este caso es mucho menos frecuente (vamos, yo no lo he hecho nunca). Así que no soy partidario de complicar el código demasiado, prefiero usar @@IDENTITY para todo.

02 marzo, 2006 08:55  
Blogger Pablo said...

Al implementar el uso de SELECT @@IDENTITY me he encontrado con que devuelve un decimal. Lo comento aquí para que quede constancia. Microsoft no tiene declarado que sea así, sólo que devuelve un valor numérico. He encontrado una discusión al respecto en http://www.theserverside.net/discussions/thread.tss?thread_id=23522, y por el final acaban comentando lo que digo. Así que actualmente estoy haciendo un casting explícito a decimal para después convertirlo a int. Algún día esto petará. Cuando Microsoft quiera.

17 julio, 2006 17:46  

Publicar un comentario

<< Home