Mon application (service WCF) utilise des contextes de données LINQ et nous avons récemment décidé de tout emballer dans une transaction. Semble fonctionner plutôt bien; Chaque appel dans le service a sa propre transaction, donc si une exception est levée, tout est annulé et aucune modification n'est validée dans la base de données.Exception lors de la tentative de création/utilisation d'une transaction interne
Cependant, nous avons la notion d'un «code de superviseur», qui peut être généré et utilisé une seule fois. Nous souhaitons que le code de superviseur soit marqué comme étant utilisé même si une erreur survient plus tard dans l'opération. Pour moi, cela suggère que je devrais utiliser une transaction interne?
donc dans ma méthode SetToUsed
, j'ai mis dans une nouvelle transaction comme ceci:
public void SetToUsed(string code)
{
// security codes explicitly need their own transaction so that they will still be marked as having been used even if the outer transaction were to be rolled back due to error
using (var securityCodeTransaction = new TransactionScope(
TransactionScopeOption.RequiresNew,
new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadUncommitted
},
EnterpriseServicesInteropOption.Automatic))
{
var returnedItems = m_safetyCodeRepository.FindAll(sc => sc.safetyCode == code &&
sc.safetyCodeTypeId == (long)GetCodeType() &&
sc.isUsed == false);
foreach (var item in returnedItems)
{
item.isUsed = true;
m_safetyCodeRepository.SaveChanges(item);
}
securityCodeTransaction.Complete();
}
}
Cependant, cela provoque une exception: System.InvalidOperationException: Connection currently has transaction enlisted. Finish current transaction and retry.
L'exception est levée sur la ligne FindAll
, qui est une enveloppe mince pour
dataContext.GetTable<tbSftSafetyCodes>().Where(exp).ToList()
Suis-je manque quelque chose, ou d'aller tout à fait à ce sujet dans le mauvais sens? Edit: Je me suis rendu compte que je n'avais pas réellement besoin d'une Transaction pour les modifications du Code Superviseur en tant que tel.
J'ai donc changé le TransactionScopeOption
à TransactionScopeOption.Suppress
à la place. Je voudrais toujours savoir pourquoi avoir la transaction interne en utilisant TransactionScopeOption.RequiresNew
n'a pas fonctionné si!
Comment la transaction externe (le cas échéant) est-elle créée? –
@Mark: la TransactionScope externe est créée de la même manière, plus haut dans la pile. – Coxy