En un flujo de trabajo de aprobación, quiero asegurarme de que los correos electrónicos de recordatorio se envíen exactamente una vez.EF eqivalent para filas afectadas de SqlCommand.ExecuteNonQuery
Con SqlCommand.ExecuteNonQuery puedo asegurar esto probando el valor de retorno. ¿Cuál es la solución recomendada con EF? De acuerdo con la documentación ObjectContext.SaveChanges no devuelve un valor equivalente.
SqlCommand ejemplo: (El TransactionScope se utiliza para deshacer la actualización de base de datos en caso de SendMail falla.)
Dim sql = "UPDATE LeaveApprovalRequests SET State = 'Reminded'" &
" WHERE ID=3 AND State <>'Reminded'"
Using scope As New TransactionScope
Using cnx As New SqlConnection(My.Settings.connectionString)
cnx.Open()
Dim cmd As New SqlCommand(sql, cnx)
If 1 = cmd.ExecuteNonQuery Then
SendMail()
End If
scope.Complete()
End Using
End Using
Al permitir la concurrencia optimista (usando ConcurrencyMode = fija en una propiedad rowversion) y agarrar la OptimisticConcurrencyException I Puedo identificar si el objeto realmente se actualizó en la tienda. Ahora, el TransactionScope (utilizado para deshacer la actualización de la base de datos si SendMail falla) genera un error de interbloqueo. ¿Por qué?
Using scope As New TransactionScope
Using ctx As New ApprovalEntities
Try
Dim approval = ctx.LeaveApprovalRequests.
Where(Function(r) r.ID = 3 And r.State = "Created"
).FirstOrDefault
If approval Is Nothing Then
Console.WriteLine("not found")
Exit Sub
End If
Threading.Thread.Sleep(4000)
approval.State = "Reminded"
ctx.SaveChanges()
SendMail()
Catch ex As OptimisticConcurrencyException
Exit Try
End Try
End Using
scope.Complete()
End Using
Para mí, la documentación dice que SaveChanges devuelve el número de objetos que intenta actualizar, no el número que actualizó en la tienda. Lo verifiqué estableciendo un punto de interrupción en SaveChanges(), cambiando el valor en SQL Server y luego reanudando. –
Exactamente. Y si puede llamar a SaveChanges() * sin * ninguna excepción, entonces EF garantiza que el número de objetos tiene la intención de actualizarse, de hecho se actualiza en la tienda o obtendrá una excepción. –
Disculpe, no leí correctamente su primer comentario (aunque destacó la parte importante). Mi caso de prueba inicial no usó concurrencia optimista, pero en mis escenarios del mundo real lo habilitaré en la mayoría de los casos. Eso deja la pregunta por qué el TransactionScope arroja un error de interbloqueo. –