Al ejecutar SubmitChanges al DataContext después de actualizar un par de propiedades con una conexión LINQ to SQL (contra SQL Server Compact Edition) obtengo una "Fila no encontrada o modificada". ChangeConflictException.
var ctx = new Data.MobileServerDataDataContext(Common.DatabasePath);
var deviceSessionRecord = ctx.Sessions.First(sess => sess.SessionRecId == args.DeviceSessionId);
deviceSessionRecord.IsActive = false;
deviceSessionRecord.Disconnected = DateTime.Now;
ctx.SubmitChanges();
La consulta genera el siguiente SQL:
UPDATE [Sessions]
SET [Is_Active] = @p0, [Disconnected] = @p1
WHERE 0 = 1
-- @p0: Input Boolean (Size = 0; Prec = 0; Scale = 0) [False]
-- @p1: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:12:02 PM]
-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: 3.5.21022.8
El problema obvio es el DONDE 0 = 1. Después de que se cargó el registro, he confirmado que todas las propiedades en "deviceSessionRecord" son correctas para incluir la clave principal. Además, cuando se detecta la "ChangeConflictException", no hay información adicional sobre por qué falló. También he confirmado que esta excepción se lanza con exactamente un registro en la base de datos (el registro que estoy intentando actualizar)
Lo extraño es que tengo una declaración de actualización muy similar en una sección de código diferente y genera el siguiente SQL y, de hecho, actualiza mi base de datos SQL Server Compact Edition.
UPDATE [Sessions]
SET [Is_Active] = @p4, [Disconnected] = @p5
WHERE ([Session_RecId] = @p0) AND ([App_RecId] = @p1) AND ([Is_Active] = 1) AND ([Established] = @p2) AND ([Disconnected] IS NULL) AND ([Member_Id] IS NULL) AND ([Company_Id] IS NULL) AND ([Site] IS NULL) AND (NOT ([Is_Device] = 1)) AND ([Machine_Name] = @p3)
-- @p0: Input Guid (Size = 0; Prec = 0; Scale = 0) [0fbbee53-cf4c-4643-9045-e0a284ad131b]
-- @p1: Input Guid (Size = 0; Prec = 0; Scale = 0) [7a174954-dd18-406e-833d-8da650207d3d]
-- @p2: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:20:50 PM]
-- @p3: Input String (Size = 0; Prec = 0; Scale = 0) [CWMOBILEDEV]
-- @p4: Input Boolean (Size = 0; Prec = 0; Scale = 0) [False]
-- @p5: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:20:52 PM]
-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: 3.5.21022.8
He confirmado que los valores de los campos primarios adecuados se han identificado tanto en el esquema de la base de datos como en el DBML que genera las clases LINQ.
Supongo que esta es una pregunta de casi dos partes:
- ¿Por qué se lanza la excepción?
- Después de revisar el segundo conjunto de SQL generado, parece que para detectar conflictos sería bueno verificar todos los campos, pero imagino que esto sería bastante ineficiente. ¿Es así como siempre funciona? ¿Existe una configuración para verificar la clave principal?
He estado luchando con esto durante las últimas dos horas, por lo que cualquier ayuda sería apreciada.
fuente
Respuestas:
Eso es desagradable, pero simple:
Verifique si los tipos de datos para todos los campos en O / R-Designer coinciden con los tipos de datos en su tabla SQL. ¡Verifique si acepta valores NULL! Una columna debe ser anulable en O / R-Designer y SQL, o no anular en ambos.
Por ejemplo, un "título" de la columna NVARCHAR se marca como NULLable en su base de datos y contiene el valor NULL. A pesar de que la columna está marcada como NOT NULLable en su O / R-Mapping, LINQ la cargará correctamente y establecerá la columna-String en nula.
El mismo síntoma aparecerá cuando los tipos de datos de un campo no coincidan con el tipo de datos en SQL, o si faltan campos, ya que LINQ no podrá asegurarse de que los datos SQL no hayan cambiado desde la lectura de los datos.
fuente
VARCHAR(MAX) NOT NULL
aVARCHAR(MAX) NULL
y esperando que funcione. Error muy simple.NUMERIC(12,8)
columna asignada a unaDecimal
propiedad. Tuve que precisar el DbType en el atributo Column[Column(DbType="numeric(12,8)")] public decimal? MyProperty ...
Primero, es útil saber qué está causando el problema. Buscar una solución en Google debería ayudar, puede registrar los detalles (tabla, columna, valor anterior, valor nuevo) sobre el conflicto para encontrar una mejor solución para resolver el conflicto más adelante:
Crea un ayudante para envolver tu sumbitChanges:
Y luego llame al código de envío de cambios:
Finalmente, registre la excepción en su controlador de excepciones global:
fuente
Hay un método en DataContext llamado Refresh que puede ayudar aquí. Le permite volver a cargar el registro de la base de datos antes de que se envíen los cambios y ofrece diferentes modos para determinar qué valores conservar. "KeepChanges" parece el más inteligente para mis propósitos, está destinado a fusionar mis cambios con cualquier cambio no conflictivo que haya ocurrido en la base de datos mientras tanto.
Si lo entiendo correctamente. :)
fuente
dc.Refresh(RefreshMode.KeepChanges,changedObject);
antes de dc.SubmitChangesEsto también puede deberse al uso de más de un DbContext.
Así por ejemplo:
Este código fallará de vez en cuando, de formas que parecen impredecibles, porque el usuario se usa en ambos contextos, se cambia y se guarda en uno y luego se guarda en el otro. La representación en memoria del usuario que posee "Algo" no coincide con lo que hay en la base de datos, por lo que aparece este error al acecho.
Una forma de evitar esto es escribir cualquier código que pueda ser llamado como método de biblioteca de tal manera que tome un DbContext opcional:
Así que ahora su método toma una base de datos opcional, y si no hay una, va y crea una. Si lo hay, simplemente reutiliza lo que se pasó. El método auxiliar facilita la reutilización de este patrón en la aplicación.
fuente
Resolví este error volviendo a arrastrar sobre una tabla desde el explorador del servidor hasta el diseñador y reconstruyendo.
fuente
Esto es lo que necesita para anular este error en el código C #:
fuente
No sé si ha encontrado alguna respuesta satisfactoria a su pregunta, pero publiqué una pregunta similar y finalmente la respondí yo mismo. Resultó que la opción de conexión predeterminada NOCOUNT estaba activada para la base de datos, lo que provocó una excepción ChangeConflictException para cada actualización realizada con Linq a Sql. Puede consultar mi publicación aquí .
fuente
Arreglé esto agregando
(UpdateCheck = UpdateCheck.Never)
a todas las[Column]
definiciones.Sin embargo, no parece una solución adecuada. En mi caso, parece estar relacionado con el hecho de que esta tabla tiene una asociación con otra tabla de la que se elimina una fila.
Esto está en Windows Phone 7.5.
fuente
En mi caso, el error se generó cuando dos usuarios con diferentes contextos de datos LINQ-to-SQL actualizaron la misma entidad de la misma manera. Cuando el segundo usuario intentó la actualización, la copia que tenía en su contexto de datos estaba obsoleta a pesar de que se leyó después de que se completó la primera actualización.
Descubrí la explicación y la solución en este artículo de Akshay Phadke: https://www.c-sharpcorner.com/article/overview-of-concurrency-in-linq-to-sql/
Aquí está el código que levanté principalmente:
Cuando miré mi ventana de salida mientras depuraba, pude ver que el valor actual coincidía con el valor de la base de datos. El "Valor Original" fue siempre el culpable. Ese fue el valor leído por el contexto de datos antes de aplicar la actualización.
Gracias a MarceloBarbosa por la inspiración.
fuente
Sé que esta pregunta ha sido respondida hace mucho tiempo, pero aquí he pasado las últimas horas golpeándome la cabeza contra la pared y solo quería compartir mi solución que resultó no estar relacionada con ninguno de los elementos de este hilo:
Almacenamiento en caché
La parte select () de mi objeto de datos estaba usando almacenamiento en caché. Cuando se trataba de actualizar el objeto, aparecía un error de Fila no encontrada o modificada.
Varias de las respuestas mencionaron el uso de diferentes DataContext y, en retrospectiva, esto es probablemente lo que estaba sucediendo, pero no me llevó instantáneamente a pensar en el almacenamiento en caché, ¡así que espero que esto ayude a alguien!
fuente
Recientemente encontré este error y descubrí que el problema no estaba en mi contexto de datos, sino con una declaración de actualización que se activaba dentro de un disparador después de que se llamaba a Commit en el contexto. El disparador intentaba actualizar un campo que no aceptaba valores NULL con un valor nulo y provocaba que el contexto fallara con el mensaje mencionado anteriormente.
Estoy agregando esta respuesta únicamente para ayudar a otros a lidiar con este error y no encontrar una solución en las respuestas anteriores.
fuente
También tengo este error debido al uso de dos contextos diferentes. Resolví este problema utilizando un contexto de datos únicos.
fuente
En mi caso, el problema estaba en las opciones de usuario de todo el servidor. Siguiendo:
https://msdn.microsoft.com/en-us/library/ms190763.aspx
Activé la opción NOCOUNT con la esperanza de obtener algunos beneficios de rendimiento:
y esto resulta que rompe los controles de Linq para las Filas Afectadas (tanto como puedo averiguarlo de las fuentes .NET), lo que lleva a ChangeConflictException
Restablecer las opciones para excluir los 512 bits solucionó el problema.
fuente
Después de emplear la respuesta de qub1n, descubrí que el problema para mí era que había declarado inadvertidamente que una columna de la base de datos era decimal (18,0). Estaba asignando un valor decimal, pero la base de datos lo estaba cambiando, eliminando la parte decimal. Esto resultó en el problema de cambio de fila.
Solo agregue esto si alguien más se encuentra con un problema similar.
fuente
solo ve con Linq2DB, mucho mejor
fuente