Откат транзакции WCF при использовании двух сервисов для обновления двух разных баз данных: одна - данные SQL, а другая - данные Couchbase. - PullRequest
0 голосов
/ 22 мая 2018

Как реализовать откат обновлений баз данных с помощью службы 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 для сохранения изменений.Транзакция. Текущий по-прежнему равен нулю.

1 Ответ

0 голосов
/ 23 мая 2018
  1. Включить поток транзакций в привязках ваших сервисов.
  2. Включить Разрешить поток транзакций в ваших контрактах на выполнение операций.
  3. Создание транзакции из клиента и вызов обеих служб в одной транзакции.

Ознакомьтесь с этим сообщением в блоге , в котором объясняются транзакции и способы их включения.Я надеюсь, что вы найдете свой ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...