Quand vous avez un code comme celui-ci:
Something something = new Something();
BlahEntities b = new BlahEntities()
b.AddToSomethingSet(something);
b.SaveChanges();
comment exécuter cette addition dans une transaction?
Vous pouvez placer votre code dans une portée de transaction
using(TransactionScope scope = new TransactionScope())
{
// Your code
scope.Complete(); // To commit.
}
TransactionScope se trouve dans l'espace de noms System.Transactions qui se trouve dans l'assembly du même nom (que vous devrez peut-être ajouter manuellement à votre projet).
ObjectContext a une propriété de connexion que vous pouvez utiliser pour gérer les transactions.
using (var context = new BlahEntities())
using (var tx = context.BeginTransaction())
{
// do db stuff here...
tx.Commit();
}
Dans le cas d'une exception, la transaction sera annulée. Comme l'appel à BeginTransaction () nécessite une connexion ouverte, il est logique d'envelopper l'appel à BeginTransaction éventuellement dans une méthode d'extension.
public static DbTransaction BeginTransaction(this ObjectContext context)
{
if (context.Connection.State != ConnectionState.Open)
{
context.Connection.Open();
}
return context.Connection.BeginTransaction();
}
Un scénario dans lequel, selon moi, cette approche pourrait être utile avec TransactionScope consiste à avoir accès à deux sources de données et à n’avoir besoin que d’un contrôle transactionnel sur l’une des connexions. Je pense que dans ce cas, TransactionScope passera à une transaction distribuée qui pourrait ne pas être requise.
Je sais que pour LINQ to SQL, le contexte de données créera une transaction pour SubmitChanges () s'il n'y a pas de transaction ambiante existante (TransactionScope est une transaction "ambiante"). Je n'ai pas vu cela documenté pour LINQ to Entities, mais j'ai constaté un comportement suggérant qu'il en soit de même pour Entity Framework.
Par conséquent, tant que vous utilisez un SubmitChanges () (L2SQL) ou SaveChanges () (Linq to Entities) pour toutes les modifications associées, vous devriez être OK sans utiliser TransactionScope. Vous avez besoin d’un TransactionScope lorsque
J'ai eu des problèmes avec TransactionScopes imbriqués. Ils sont censés fonctionner et les cas de test simples fonctionnent, mais lorsque je suis dans le code de production, la transaction "interne" semble être le même objet que la transaction externe. Les symptômes incluent des erreurs "transaction validée, vous ne pouvez plus utiliser cette transaction" ou "cet objet de transaction a déjà été supprimé". Les erreurs se produisent dans la transaction externe après que la transaction interne a effectué son travail.
using System.Transactions;
using (TransactionScope scope = new TransactionScope())
{
try
{
using(DataContext contextObject = new DataContext(ConnectionString))
{
contextObject.Connection.Open();
// First SaveChange method.
contextObject.SaveChanges();
// Second SaveChange method.
contextObject.SaveChanges();
//--continue to nth save changes
// If all execution successful
scope.Complete();
}
}
catch(Exception ex)
{
// If any exception is caught, roll back the entire transaction and end the scope.
scope.Dispose();
}
finally
{
// Close the opened connection
if (contextObject.Connection.State == ConnectionState.Open)
{
contextObject.Connection.Close();
}
}
}
Recherchez le lien ci-dessous pour une explication détaillée https://msdn.Microsoft.com/en-us/data/dn456843.aspx
Dans toutes les versions d'Entity Framework, chaque fois que vous exécutez SaveChanges () pour insérer, mettre à jour ou supprimer de la base de données, l'infrastructure encapsule cette opération dans une transaction. Cette transaction ne dure que le temps nécessaire pour exécuter l'opération, puis se termine. Lorsque vous exécutez une autre opération de ce type, une nouvelle transaction est lancée. Pour la dernière version de Entity Framework: 6.0 +
Lire plus ici: EntityFramework and Transaction