web-dev-qa-db-fra.com

Comment utiliser les transactions avec Entity Framework?

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?

27
pupeno

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).

26
Shiraz Bhaiji

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.

55
Kim Major

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

  1. Enregistrement de plusieurs modifications avec plusieurs SubmitChanges/SaveChanges pour une transaction.
  2. Mise à jour de plusieurs sources de données au sein d'une transaction (par exemple, fournisseur SQL d'adhésion à Linq et ASP.NET).
  3. Appeler d'autres méthodes pouvant effectuer leurs propres mises à jour.

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.

9
Cylon Cat
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

1
Sabyasachi Mishra

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

0
Mesut Talebi2