why transaction transacciones practices not framework dead best entity-framework transactions

entity framework - transaction - Marco de la entidad: Uso de transacciones y retrocesos... ¿Posible?



transaction rollback entity framework (3)

Problema: (con Sql 2005)

  • ¿Cómo puedo consultar la base de datos mientras la transacción está activa? (Ya que bloquea la mesa)
  • ¿Cómo se puede deshacer una transacción y luego cerrarla para permitir que se consulte la tabla?

Entonces encontré esto:

[TestMethod] public void CreateUser() { TransactionScope transactionScope = new TransactionScope(); DataContextHandler.Context.AddToForumUser(userToTest); DataContextHandler.Context.SaveChanges(); DataContextHandler.Context.Dispose(); }

Donde DataContextHandler es solo un simple singleton que expone el objeto de contexto para mis entidades. Esto parece funcionar como lo pensarías. Crea al usuario, lo guarda y luego lo retrotrae cuando termina el programa. (Finaliza la prueba IE)

Problema: ¿Cómo fuerzo la transacción para que se retrotraiga y se mate solo para que pueda consultar la tabla?

Motivo: Para fines de prueba, quiero asegurarme de que el usuario:

  • Está guardado
  • Puede ser consultado correctamente para probar su existencia
  • Se elimina (datos no deseados)
  • Se puede consultar para asegurarse de que se eliminó.

A partir de ahora, solo puedo obtener la reversión de la transacción si la prueba finaliza Y no puedo encontrar la forma de consultar con la transacción:

[TestMethod] public void CreateUser() { ForumUser userToTest = new ForumUser(); TransactionScope transactionScope = new TransactionScope(); DataContextHandler.Context.AddToForumUser(userToTest); DataContextHandler.Context.SaveChanges(); Assert.IsTrue(userToTest.UserID > 0); var foundUser = (from user in DataContextHandler.Context.ForumUser where user.UserID == userToTest.UserID select user).Count(); //KABOOM Can''t query since the //transaction has the table locked. Assert.IsTrue(foundUser == 1); DataContextHandler.Context.Dispose(); var after = (from user in DataContextHandler.Context.ForumUser where user.UserID == userToTest.UserID select user).Count(); //KABOOM Can''t query since the //transaction has the table locked. Assert.IsTrue(after == 0); }

ACTUALIZACIÓN Esto funcionó para el retroceso y la comprobación, pero aún no se puede consultar dentro de la sección de uso:

using(TransactionScope transactionScope = new TransactionScope()) { DataContextHandler.Context.AddToForumUser(userToTest); DataContextHandler.Context.SaveChanges(); Assert.IsTrue(userToTest.UserID > 0); //Still can''t query here. } var after = (from user in DataContextHandler.Context.ForumUser where user.UserID == userToTest.UserID select user).Count(); Assert.IsTrue(after == 0);


En mi caso elimino todos los registros de una tabla a través de SQL simple ya que EF no proporciona una funcionalidad para esto. Después de eso agrego algunas entidades nuevas, pero cuando falla, la tabla no debe estar vacía. El uso de MSDTC (TransactionScope) no parece posible para mí. Reduje la transacción a la base de datos:

Mi código:

using (var transaction = context.Connection.BeginTransaction()) { // delete all base.DeleteAll<TESTEntity>(context); // add all foreach (var item in items) { context.TESTEntity.AddObject(item); } try { context.SaveChanges(); transaction.Commit(); return true; } catch (Exception ex) { Logger.Write("Error in Save: " + ex, "Error"); transaction.Rollback(); return false; } }

Y aquí las funciones de ayuda

protected void DeleteAll<TEntity>(ObjectContext context) where TEntity : class { string tableName = GetTableName<TEntity>(context); int rc = context.ExecuteStoreCommand(string.Format(CultureInfo.InvariantCulture, "DELETE FROM {0}", tableName)); } protected string GetTableName<TEntity>(ObjectContext context) where TEntity : class { string snippet = "FROM [dbo].["; string sql = context.CreateObjectSet<TEntity>().ToTraceString(); string sqlFirstPart = sql.Substring(sql.IndexOf(snippet) + snippet.Length); string tableName = sqlFirstPart.Substring(0, sqlFirstPart.IndexOf("]")); return tableName; }


Pude resolver un problema muy similar usando este fragmento de código:

var connection = new EntityConnection("name=MyEntities"); connection.Open(); var tran = connection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted); try { var dataContext = new MyEntities(connection); //CRUD operation1 //CRUD operation2 //CRUD operation3 ... Assert.AreEqual(expected, actual); } catch { throw; } finally { tran.Rollback(); connection.Close(); }

Donde MyEntities es el EF DataModel. La parte crucial es la configuración de la transacción: System.Data.IsolationLevel.ReadUncommitted .
Usando este nivel de aislamiento, las consultas SQL pueden leer los cambios realizados dentro de la transacción. También necesita crear una conexión explícitamente como lo hago en la primera y segunda línea. No pude hacerlo funcionar usando TransactionScope desafortunadamente.


De MSDN ;

"SaveChanges opera dentro de una transacción. SaveChanges revertirá esa transacción y generará una excepción si no se puede conservar ninguno de los objetos ObjectStateEntry sucios".

Por lo tanto, parece que no hay necesidad de agregar explícitamente su propio manejo de transacciones a través de TransactionScope .