Как реализовать откат обновлений баз данных с помощью службы WCF, когда я использую две разные службы для обновления двух разных баз данных: одна - данные SQL, а другая - данные Couchbase?
Код, как показано ниже:
My web.config looks like this:
Web.Config:
<system.serviceModel>
<diagnostics>
<messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<behaviors>
<serviceBehaviors>
<behavior name="TransactionBehavior">
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<!--<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />-->
<serviceMetadata httpGetEnabled="True" />
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="wsHttpTransactionBinding" receiveTimeout="00:20:00" sendTimeout="00:20:00" bypassProxyOnLocal="false" transactionFlow="true" maxReceivedMessageSize="2147483647" messageEncoding="Mtom">
<!--<reliableSession enabled="false" />-->
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="TransactionBehavior" name="BankingService.AccountService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpTransactionBinding" name="wsHttpEndPoint" contract="SharedLib.IAccountService" />
</service>
</services>
<!--Fix could not activate service error-->
<serviceHostingEnvironment minFreeMemoryPercentageToActivateService="1" multipleSiteBindingsEnabled="true">
<!--<serviceHostingEnvironment>-->
<serviceActivations>
<add relativeAddress="AccountService.svc" service="BankingService.AccountService" factory="WebApp.UnityServiceHostFactory, WebApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</serviceActivations>
</serviceHostingEnvironment>
<client>
<endpoint address="http://localhost:9003/AccountService.svc" behaviorConfiguration="ImpersonationBehavior" binding="wsHttpBinding" bindingConfiguration="wsHttpTransactionBinding" contract="SharedLib.IAccountService" name="wsHttpEndPoint" kind="" endpointConfiguration="" />
</client>
</system.serviceModel>
App.config:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpTransactionBinding" transactionFlow="true" openTimeout="00:10:00" useDefaultWebProxy="true" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" receiveTimeout="00:20:00" sendTimeout="00:20:00" maxReceivedMessageSize="2147483647" messageEncoding="Mtom">
<security mode="None">
</security>
</binding>
</wsHttpBinding>
<netTcpBinding>
<binding name="netTcpTransactionBinding" transactionFlow="true" sendTimeout="00:20:00" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://localhost:9003/AccountService.svc"
behaviorConfiguration="ImpersonationBehavior" binding="wsHttpBinding"
bindingConfiguration="wsHttpTransactionBinding" contract="SharedLib.IAccountService"
name="wsHttpEndPoint" kind="" endpointConfiguration="" />
</client>
</system.serviceModel>
ServiceContract is as below:
IAccountService.cs
[ServiceContract]
public interface IAccountService
{
[OperationContract]
Task<IEnumerable<Account>> GetAccounts();
[OperationContract, TransactionFlow(TransactionFlowOption.Allowed)]
Task<bool> Debit(int accountID, int amount);
[OperationContract, TransactionFlow(TransactionFlowOption.Allowed)]
Task<bool> Credit(int accountID, int amount);
[OperationContract]
Task<int> GetBalance(int accountID);
[OperationContract]
Task<MiniStatement> GetMiniStatement(int accountID);
}
Service Implementation is as below:
Account.cs
[ServiceBehavior(
TransactionIsolationLevel =
System.Transactions.IsolationLevel.ReadCommitted,ConcurrencyMode = ConcurrencyMode.Multiple, ReleaseServiceInstanceOnTransactionComplete = false)]
public class AccountService : IAccountService
{
BankRepository bankRepository = new BankRepository();
CouchbaseRepository couchbaseRepository = new CouchbaseRepository();
public AccountService()
{
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public Task<bool> Credit(int accountID, int amount)
{
var creditAccountTask = Task.Run(async () =>
{
return await bankRepository.CreditAccount(accountID, amount, Transaction.Current);
});
var result = creditAccountTask.ContinueWith(async (t) =>
{
return t.Result != null ? await couchbaseRepository.CreditAccount(accountID, t.Result) : false;
}, TaskContinuationOptions.OnlyOnRanToCompletion);
return result.Result;
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public Task<bool> Debit(int accountID, int amount)
{
var debitAccountTask = Task.Run(async () =>
{
return await bankRepository.DebitAccount(accountID, amount, Transaction.Current);
});
var result = debitAccountTask.ContinueWith(async (t) =>
{
return t.Result != null ? await couchbaseRepository.DebitAccount(accountID, t.Result) : false;
}, TaskContinuationOptions.OnlyOnRanToCompletion);
return result.Result;
}
public Task<IEnumerable<Account>> GetAccounts()
{
return bankRepository.GetAccounts();
}
public Task<int> GetBalance(int accountID)
{
return bankRepository.GetBalanceByAccountID(accountID);
}
public Task<MiniStatement> GetMiniStatement(int accountID)
{
return couchbaseRepository.GetTransactionStatement(accountID);
}
}
Транзакции все еще не работают, когда я использую EF для сохранения изменений.Транзакция. Текущий по-прежнему равен нулю.