UPDATE (2010-12-21): Completamente reescribí esta pregunta en función de las pruebas que he estado haciendo. Además, solía ser una pregunta específica de POCO, pero resulta que mi pregunta no es necesariamente específica de POCO.OptimisticConcurrencyException no funciona en Entity Framework en ciertas situaciones
Estoy usando Entity Framework y tengo una columna de marca de tiempo en la tabla de mi base de datos que se debe usar para rastrear los cambios para una concurrencia optimista. Establecí el modo de concurrencia para esta propiedad en el Diseñador de Entidades en "Solucionado" y obtengo resultados inconsistentes. Aquí hay un par de escenarios simplificados que demuestran que la comprobación de simultaneidad funciona en un escenario pero no en otro.
con éxito tiros OptimisticConcurrencyException:
Si hay que adjuntar una entidad desconectada, entonces SaveChanges lanzará una OptimisticConcurrencyException si hay un conflicto de marca de tiempo:
[HttpPost]
public ActionResult Index(Person person) {
_context.People.Attach(person);
var state = _context.ObjectStateManager.GetObjectStateEntry(person);
state.ChangeState(System.Data.EntityState.Modified);
_context.SaveChanges();
return RedirectToAction("Index");
}
no tirar OptimisticConcurrencyException:
Por otro lado, si recupero una nueva copia de mi entidad de la d atabase y hago una actualización parcial en algunos campos, y luego llamo SaveChanges(), a continuación, a pesar de que existe un conflicto de marca de tiempo, no consigo un OptimisticConcurrencyException:
[HttpPost]
public ActionResult Index(Person person) {
var currentPerson = _context.People.Where(x => x.Id == person.Id).First();
currentPerson.Name = person.Name;
// currentPerson.VerColm == [0,0,0,0,0,0,15,167]
// person.VerColm == [0,0,0,0,0,0,15,166]
currentPerson.VerColm = person.VerColm;
// in POCO, currentPerson.VerColm == [0,0,0,0,0,0,15,166]
// in non-POCO, currentPerson.VerColm doesn't change and is still [0,0,0,0,0,0,15,167]
_context.SaveChanges();
return RedirectToAction("Index");
}
Basado en SQL, parece que Entity Framework está ignorando el nuevo VerColm (que es la propiedad de marca de tiempo) y en su lugar utiliza el VerColm cargado originalmente. Debido a esto, nunca arrojará una OptimisticConcurrencyException.
ACTUALIZACIÓN: Adición de información adicional por la petición de Jan:
Tenga en cuenta que también añadí comentarios al código anterior para que coincida con lo que veo en mi acción del controlador mientras se trabaja a través de este ejemplo.
Este es el valor de la VerColm en mi base de datos antes de la actualización: 0x0000000000000FA7
Esto es lo que el Analizador de SQL muestra al hacer la actualización:
exec sp_executesql N'update [dbo].[People]
set [Name] = @0
where (([Id] = @1) and ([VerColm] = @2))
select [VerColm]
from [dbo].[People]
where @@ROWCOUNT > 0 and [Id] = @1',N'@0 nvarchar(50),@1 int,@2 binary(8)',@0=N'hello',@1=1,@2=0x0000000000000FA7
Tenga en cuenta que @ 2 debería haber sido 0x0000000000000FA6 , pero es 0x0000000000000FA7
Aquí está el VerColm en mi base de datos después de la actualización: 0x0000000000000FA8
¿Alguien sabe cómo puedo evitar este problema? Me gustaría que Entity Framework arroje una excepción cuando actualizo una entidad existente y hay un conflicto de marca de tiempo.
Gracias
Por favor, publique el código que hace el ahorro. –
No puedo reproducir esto. Obtengo una OptimisticConcurrencyException cuando trato de guardar la entidad cargada y modificada con un conflicto de marca de tiempo. ¿Estás seguro de que tienes un conflicto de marca de tiempo? ¿Puedes publicar tu consulta SQL perfilada? – Jan
Hola Jan, agregué información adicional arriba según tu solicitud. –