Row not found or changed : Javier Luna blog

Sunday, February 03, 2008

Row not found or changed

Uno de los exceptions que por lo general aparecen cuando estas trabajando con Linq to Sql, es el ChangeConflictException.

El mensaje tradicional correspondiente a este exception es: Row not found or changed.

Cuando recien estas construyendo el software. Muy probablemente te encuentres con este mensaje. Si no te calmas en encontrar la solucion, te podria sacar de tus casillas.

Lo que sucede es que generalmente la base de datos esta aun ajustandose, cambiando si un campo de la tabla permitira nulo o NO, por ejemplo. Si un tipo de dato BIT sera cambiado a un CHAR(1), por decir algo.

Y otras simpleces a nivel de base de datos.

Pero aquellos cambios, por la premura del tiempo o por alguna circunstancia, NO son plasmados tambien en el modelo que propone Linq To Sql, dentro de tu aplicativo.

Y he alli el origen del problema.

Cuando estas desarrollando software y te apoyas en Linq To Sql para facilitarte la construccion de los Business Entities, debes estar pendiente que la estructura de tablas de tu Base de Datos sincronize con las caracteristicas de los Business Entities asociada a cada tabla.

Al realizar una operacion de actualizacion o eliminacion contra la Base de Datos de un elemento en particular, Linq To Sql no construye la sentencia SQL en funcion a un WHERE mykeyfield = @mykeyfield

Linq To Sql realiza un WHERE en funcion al estado actual del registro previo al cambio.

Y si alguna caracteristica de tu Base de Datos NO esta sincronizada con el modelo de Linq To Sql, pues veras este mensajito constamente: Row not found or changed.

Por citar una ejemplo, que un campo en la base de datos haya sido cambio para NO permitir nulo, cuando antes si lo permitia. Pero sin embargo dicho cambio NO se realizo de la misma manera en el modelo de Linq To Sql, se entiende que para Linq To Sql aquel campo aun permite nulo.

Entonces al construir su WHERE, Linq To Sql, constuira una lista de campos para hacer el match del estado anterior del registro y con un myfieldchange IS NULL dentro de todos ellos.

En lugar de algo distinto al nosotros saber, que a nivel de Base de Datos, esto ya NO esta permitido.

En consecuencia, Linq To Sql NO puede encontrar el registro anterior, debido a que efectivamente este ya NO existe, bajo esas circunstancias.

La solución pasa por simplemente sincronizar la estructura de tu Base de Datos a nivel de campos con tu modelo de Linq To Sql.

Trabajo facil!

4 comments:

jaime said...

Interesante tu apreciacion.
Yo personalmente veo todo esto de Linq To Sql de una manera muy desconfiada. He hecho solo un par de pruebas pero no tengo claro como se integra con un diseño escalable y bien estructurado (N Capas).
Te dejo este link con algunas preguntas:
http://guy.dotnet-expertise.com/PermaLink,guid,dedfda5a-629c-4a9d-9695-c72fba181aa8.aspx
Supongo que cuando Scott Guthrie haga la demo de N Capas (varios meses esperando ya voy) veremos cual es la verdad de todo este asunto.
Un ultimo punto, creo que la gente NHibernate esta trabajando para sacar LINQ to NHibernate, la verdad seria genial y creo es la mejor opcion en ORM que existe en este momento y si le sumas LINQ a eso, pues como dicen los españoles "OLE".
Salu2

kevin bosch said...

NO te olvides de revisar el ADO.NET Entity Framework, el cual se monta sobre Linq To Sql.

Pero, de una forma o de otra, NO deberias estar esperado que el maestro Scott Guthrie nos muestra la verdad verdadera de como se desarrolla un aplicativo de N Capas haciendo uso del Linq To Sql.

Debes encontrar por ti mismo la manera de hacer calzar el Linq To Sql en tu propia forma de hacer las cosas al construir software.

Realizaras muchos intentos, y alguno de ellos te convencera mas que el anterior. O te sera mas util en ciertos escenarios que otros.

NO existe la verdad verdadera.

Anonymous said...

Hola, yo tengo el mismo error y no se como solucionarlo, a mi me sale cuando intento eliminar un registro de la base de datos, el código que utilizo es el siguiente

El codigo que estoy ejecutando es el siguiente y en la linea que esta saliendo el error es (dd.SubmitChanges();)

public String gmtdEliminar(Aplicacion tAplicacion)
{
String strResultado;
try
{
using (datosDominio dd = new datosDominio())
{
dd.Aplicacions.Attach(tAplicacion);
dd.Aplicacions.DeleteOnSubmit(tAplicacion);
dd.SubmitChanges();
strResultado = 'Registro Eliminado';
}
}
catch (Exception ex)
{
strResultado = 'Ocurri¢ un error al Eliminar el registro' + ex.Message ;
}
return strResultado;
}

utilizo metodos para insertar y modificar y todo funciona bien.

Muchas Gracias.

Anonymous said...

"La solución pasa por simplemente sincronizar la estructura de tu Base de Datos a nivel de campos con tu modelo de Linq To Sql."

Consulta: ¿como es que se hace esto?

desde ya muchas gracias.
Ariel