Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EnlistTransaction fails starting saga when using SqlAzure #244

Closed
brunobertechini opened this issue Nov 20, 2016 · 21 comments
Closed

EnlistTransaction fails starting saga when using SqlAzure #244

brunobertechini opened this issue Nov 20, 2016 · 21 comments

Comments

@brunobertechini
Copy link

I am not sure if this is the same problem from this issue #201 .

Scenario:

  1. Web sends a command MyCommand
  2. Endpoint Handler process command and publish an event MyEvent
  3. A Saga should be started with this event MyEvent (IAmStartedByMessages). This saga has a custom Saga finder using Synchronized Session:
public async Task<MySagaData> FindBy(MyEvent message, SynchronizedStorageSession storageSession, ReadOnlyContextBag context)
        {
            var sagaContext = context as IInvokeHandlerContext;
            int tenantId = Convert.ToInt32(sagaContext.MessageHeaders[MessageHeaders.TenantId]);

            var dbSession = storageSession.Session();
            return await GetSagaFromDB(dbSession, tenantId, message.ConnectionId);
        }

private async Task<MySagaData> GetSagaFromDB(ISession session, int tenantId, Guid connectionId)
        {
            var saga = session.QueryOver<SkyHubNotSyncedOrderImporterSagaData>()
                              .Where(x => x.TenantId == tenantId && x.ConnectionId == connectionId)
                              .SingleOrDefault();

            // If a saga can't be found Task.FromResult(null) should be returned
            return await Task.FromResult(saga);
        }


And this fails with exception:

2016-11-20T13:14:47  PID[4344] Information System.NotSupportedException: Specified method is not supported.
2016-11-20T13:14:47  PID[4344] Information    at System.Data.Common.DbConnection.EnlistTransaction(Transaction transaction)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.Persistence.NHibernate.NHibernateSynchronizedStorageAdapter.OpenConnection(SessionFactoryImpl sessionFactoryImpl, Transaction ambientTransaction) in C:\Build\src\NServiceBus.NHibernate\SynchronizedStorage\NHibernateSynchronizedStorageAdapter.cs:line 55
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.Persistence.NHibernate.NHibernateSynchronizedStorageAdapter.<>c__DisplayClass4_0.<TryAdapt>b__0() in C:\Build\src\NServiceBus.NHibernate\SynchronizedStorage\NHibernateSynchronizedStorageAdapter.cs:line 49
2016-11-20T13:14:47  PID[4344] Information    at System.Lazy`1.CreateValue()
2016-11-20T13:14:47  PID[4344] Information    at System.Lazy`1.LazyInitValue()
2016-11-20T13:14:47  PID[4344] Information    at System.Lazy`1.get_Value()
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.Persistence.NHibernate.NHibernateLazyAmbientTransactionSynchronizedStorageSession.<>c__DisplayClass2_0.<.ctor>b__0() in C:\Build\src\NServiceBus.NHibernate\SynchronizedStorage\NHibernateAmbientTransactionSynchronizedStorageSession.cs:line 19
2016-11-20T13:14:47  PID[4344] Information    at System.Lazy`1.CreateValue()
2016-11-20T13:14:47  PID[4344] Information    at System.Lazy`1.LazyInitValue()
2016-11-20T13:14:47  PID[4344] Information    at System.Lazy`1.get_Value()
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.Persistence.NHibernate.NHibernateLazyAmbientTransactionSynchronizedStorageSession.get_Session() in C:\Build\src\NServiceBus.NHibernate\SynchronizedStorage\NHibernateAmbientTransactionSynchronizedStorageSession.cs:line 22
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.SynchronizedStorageSessionExtensions.Session(SynchronizedStorageSession session) in C:\Build\src\NServiceBus.NHibernate\SynchronizedStorageSessionExtensions.cs:line 20
2016-11-20T13:14:47  PID[4344] Information    at MySagaFinder.<FindBy>d__0.MoveNext() in ****\MySagaFinder.cs:line 27 (Removed sensitive data)
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.CustomFinderAdapter`2.<Find>d__0.MoveNext() in C:\Build\src\NServiceBus.Core\Sagas\CustomFinderAdapter.cs:line 0
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.SagaPersistenceBehavior.<Invoke>d__1.MoveNext() in C:\Build\src\NServiceBus.Core\Sagas\SagaPersistenceBehavior.cs:line 42
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.LoadHandlersConnector.<Invoke>d__1.MoveNext() in C:\Build\src\NServiceBus.Core\Pipeline\Incoming\LoadHandlersConnector.cs:line 40
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.InvokeSagaNotFoundBehavior.<Invoke>d__0.MoveNext() in C:\Build\src\NServiceBus.Core\Sagas\InvokeSagaNotFoundBehavior.cs:line 16
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.MutateIncomingMessageBehavior.<Invoke>d__0.MoveNext() in C:\Build\src\NServiceBus.Core\Pipeline\MutateInstanceMessage\MutateIncomingMessageBehavior.cs:line 28
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.DeserializeLogicalMessagesConnector.<Invoke>d__1.MoveNext() in C:\Build\src\NServiceBus.Core\Pipeline\Incoming\DeserializeLogicalMessagesConnector.cs:line 31
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.InvokeAuditPipelineBehavior.<Invoke>d__1.MoveNext() in C:\Build\src\NServiceBus.Core\Audit\InvokeAuditPipelineBehavior.cs:line 18
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.SubscriptionReceiverBehavior.<Invoke>d__1.MoveNext() in C:\Build\src\NServiceBus.Core\Routing\MessageDrivenSubscriptions\SubscriptionReceiverBehavior.cs:line 29
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.MutateIncomingTransportMessageBehavior.<Invoke>d__0.MoveNext() in C:\Build\src\NServiceBus.Core\Pipeline\MutateTransportMessage\MutateIncomingTransportMessageBehavior.cs:line 27
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.UnitOfWorkBehavior.<Invoke>d__0.MoveNext() in C:\Build\src\NServiceBus.Core\UnitOfWork\UnitOfWorkBehavior.cs:line 26
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.UnitOfWorkBehavior.<Invoke>d__0.MoveNext() in C:\Build\src\NServiceBus.Core\UnitOfWork\UnitOfWorkBehavior.cs:line 48
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.ProcessingStatisticsBehavior.<Invoke>d__0.MoveNext() in C:\Build\src\NServiceBus.Core\Performance\Statistics\ProcessingStatisticsBehavior.cs:line 25
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.ReceivePerformanceDiagnosticsBehavior.<Invoke>d__2.MoveNext() in C:\Build\src\NServiceBus.Core\Performance\Statistics\ReceivePerformanceDiagnosticsBehavior.cs:line 40
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at Abp.NServiceBus.AbpNServiceBusUnitOfWork.<Invoke>d__1.MoveNext() in C:\a\1\s\libs\Abp.NServiceBus\Abp.NServiceBus\UnitOfWork\AbpNServiceBusUnitOfWork.cs:line 49
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.TransportReceiveToPhysicalMessageProcessingConnector.<Invoke>d__1.MoveNext() in C:\Build\src\NServiceBus.Core\Pipeline\Incoming\TransportReceiveToPhysicalMessageProcessingConnector.cs:line 37
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.MainPipelineExecutor.<Invoke>d__1.MoveNext() in C:\Build\src\NServiceBus.Core\Pipeline\MainPipelineExecutor.cs:line 32
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.Transport.SQLServer.ReceiveStrategy.<TryProcessingMessage>d__12.MoveNext() in C:\Build\src\NServiceBus.SqlServer\Receiving\ReceiveStrategy.cs:line 33
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2016-11-20T13:14:47  PID[4344] Information    at NServiceBus.Transport.SQLServer.ReceiveWithTransactionScope.<TryProcess>d__4.MoveNext() in C:\Build\src\NServiceBus.SqlServer\Receiving\ReceiveWithTransactionScope.cs:line 99
2016-11-20T13:14:47  PID[4344] Information --- End of stack trace from previous location where exception was thrown ---
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2016-11-20T13:14:47  PID[4344] Information    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
@brunobertechini
Copy link
Author

When enabling Outbox against SqlAzure NServiceBus shows:

[11/20/2016 16:08:49 > c40786: INFO] 2016-11-20 16:08:49.232 WARN  NServiceBus.Features.DtcRunningWarning The MSDTC service is running on this machine.
[11/20/2016 16:08:49 > c40786: INFO] Because Outbox is enabled disabling MSDTC is recommended. This ensures that the Outbox behavior is working as expected and no other resources are enlisting in distributed transactions.

I'd expect no DTC enabled on SqlAzure, but:
The exception goes away when enabling outbox even though the warning above is still showing

@MarcinHoppe
Copy link
Contributor

@brunobertechini Thanks for reporting this.

Where are you hosting your saga? Is it within the same App Service or elsewhere?

Also, are you using a single Azure SQL Database for both the transport and persistence?

@brunobertechini
Copy link
Author

brunobertechini commented Nov 21, 2016

@MarcinHoppe I am using the same SqlAzure for Transport and Persistence.

I am hosting the endpoint using Azure WebJobs (self hosted) in the same AppService

And I am also using NHibernate.SqlAzure driver

@MarcinHoppe
Copy link
Contributor

@brunobertechini Can you post the configuration of all your endpoints with the sensitive parts redacted? Are all the connection strings exactly the same?

@MarcinHoppe
Copy link
Contributor

@brunobertechini Are you still experiencing this issue?

@brunobertechini
Copy link
Author

brunobertechini commented Nov 27, 2016

Yes I am.. here is my endpoint config:

All connection strings are the same.
I have one config object wrapping them all.
I read one conn string from App.config and set it to:
config.TransportConnString
config.PersistenceConnString

 // Endpoint Level Config
 endpointConfiguration.PurgeOnStartup(false);
 endpointConfiguration.SendFailedMessagesTo(config.ErrorQueue); // error
 endpointConfiguration.AuditProcessedMessagesTo(config.AuditQueue); // audit

 // Transport
 var transport = endpointConfiguration.UseTransport<SqlServerTransport>();
 transport.ConnectionString(config.TransportConnectionString);
 transport.DefaultSchema(config.DatabaseSchemaName);

 // MaxConcurrencyLevel
endpointConfiguration.LimitMessageProcessingConcurrencyTo(config.MaximumConcurrencyLevel.Value);

 // Persistence
 var nhConfiguration = new NHibernate.Cfg.Configuration
 {
    Properties =
               {
                    ["dialect"] = "NHibernate.Dialect.MsSql2012Dialect",
                    ["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider",
                    ["connection.driver_class"] ="NHibernate.SqlAzure.SqlAzureClientDriver,NHibernate.SqlAzure",
                    ["default_schema"] = config.DatabaseSchemaName,
                    ["connection.connection_string"] = config.PersistenceConnectionString
               }
  };

  var persistence = endpointConfiguration.UsePersistence<NHibernatePersistence>();
  persistence.UseConfiguration(nhConfiguration);

  // Outbox
  endpointConfiguration.EnableOutbox(); // this line was enabled just to make it work for now

  // Unobtrusive Message Mode
  endpointConfiguration.UseAbpNServiceBusMessageConventions(); // my custom conventions

  // Container
  endpointConfiguration.UseContainer<WindsorBuilder>(
  customizations: customizations =>
                {
                    customizations.ExistingContainer(IocManager.IocContainer);
                });

  // Recoverability
  endpointConfiguration.Recoverability()
                .Immediate(customizations: immediate =>
                {
                    immediate.NumberOfRetries(config.ImmediateRetries);
                })
                .Delayed(customizations: delayed =>
                {
                    delayed.NumberOfRetries(config.DelayedRetries);
                    delayed.TimeIncrease(TimeSpan.FromSeconds(config.DelayedRetriesTimeIncreaseInSeconds));
                });

  // Session session Mutator to propagate Headers to all output messages
  endpointConfiguration.RegisterComponents(
                registration: components =>
                {       components.ConfigureComponent<MySessionHeaderAppender(DependencyLifecycle.InstancePerCall);
                });

  // UnitOfWork          endpointConfiguration.Pipeline.Register(typeof(MyCustomUnitOfWorkBehavior),MyCustomBehavior);

@MarcinHoppe
Copy link
Contributor

@brunobertechini How does your custom unit of work behavior look like? Does it interact with the database in any way?

@brunobertechini
Copy link
Author

Yes. It starts the custom UoW and calls next(); and commit UnitOfWork (EF6) after next

// Start UnitOfWork
IUnitOfWorkManager uowManager = IocManager.Instance.Resolve<IUnitOfWorkManager>();
IUnitOfWorkCompleteHandle unitOfWork= uowManager.Begin();

// Call next step in pipeline
await next();

// Complete UnitOfWork if no exception is raised
await unitOfWork.CompleteAsync();

@brunobertechini
Copy link
Author

Should I have one database catalog specific for queues (separated from business data) ?

By reading SqlTransport Deployment Options it seems multi-instance/catalog is deprecated:

The multi-instance option is deprecated and not recommended for new projects.

@brunobertechini
Copy link
Author

brunobertechini commented Dec 2, 2016

My goal is to import third-party data for processing. New Entities from a third party provider.

I have a restriction on how many calls I can make and also im worried about performance issues:

For example if I have 2000 entities to import i need to do 20 calls (100 entities each - api restriction) and publish an event for each one.

The problem is, for each entity I need to call another api method to mark the entity as imported/processed. That makes 40 calls to thirdpary api. But since the SetAsImported call might fail, I cant do that inside one single handler. And im sending commands to SetAsImported to another handlers.

That way I will have 100 inserts for business data and 100 commands going out. All persisted to SqlAzure.

Bruno

@MarcinHoppe
Copy link
Contributor

@brunobertechini Is your EF data in the same database? If it is, please make sure that you follow the trick described here to avoid DTC escalation when using EF:

https://docs.particular.net/nservicebus/sqlserver/entity-framework

If your EF data is in another database, then you might have to create a new TransactionScope with TransactionScopeOption.Suppress or use Enlist=false parameter in your EF connection string to prevent DTC escalation.

Does this help?

@brunobertechini
Copy link
Author

They are all in the same database for now. Considering split.

If I does not escalate to DTC will I have all messages and business data being processed inside a handler to act as one single transaction from unit of work ? I.e.: will all rollback together if either business data and/or messages fail to be processed?

@brunobertechini
Copy link
Author

Im using EF6 code first and the context is being injected by Aspnetboilerplate library.

I dont see enough info in that link to "share" ef connection. As per my understanding this states that NHibernate and EF6 must share the sabe DBConnection to participate in the transaction right ?

Bruno

@MarcinHoppe
Copy link
Contributor

@brunobertechini That's a lot of questions and I think they go beyond the original issue 😄.

Would you mind posting these questions to support@particular.net? I think it will be easier for us to resolve your issue through that channel. Thanks!

@MarcinHoppe
Copy link
Contributor

@brunobertechini You can CC me (marcin.hoppe at particular.net) and I will get at it directly. Thanks!

@brunobertechini
Copy link
Author

brunobertechini commented Dec 2, 2016

👍

Can you just shed some light at this one

As per my understanding the link above (for EF Caveats) states that NHibernate and EF6 must share the same DBConnection to participate in the transaction to avoid the exception mentioned in the first comment? I.E.: avoid escalating to DTC ?

What I would like to know is if the exception mentioned above is because the transport is trying to escalate to DTC.

@MarcinHoppe
Copy link
Contributor

I think the architecture here could be simplified to achieve the same goal of having transactional consistency between the transport, EF context and sagas.

  • If you want to rely on transaction opened by the transport, you don't need to roll your own unit of work. EF should work fine with the ambient transaction opened by the transport (how to keep it lightweight so that it does not escalate to the DTC is a separate thing),
  • If you want to use your own unit of work and have it commit / rollback EF transactions depending on whether the NSB pipeline threw an exception or not, you don't need to hook it to the existing transaction scope. You can use Enlist=false in your EF connection string to prevent EF from escalating to the DTC.

Does this make sense?

I will still try to replicate this solution to see if I can get the same exception.

@MarcinHoppe
Copy link
Contributor

I smoke tested the Sql Transport, NHibernate and EF sample without Outbox against a single Azure SQL Database for transport, persistence and business data. It worked fine and I observed no DTC escalation.

@brunobertechini Did my last response help in any way? Have you created the support case where I could chime in?

@brunobertechini
Copy link
Author

@MarcinHoppe sorry didnt have time to go deeper on this matter. I will create a reproduction of this code. I am pretty sure this is related to AspNetBoilerplate framework and how it handles EF transactions.

Bruno

@SzymonPobiega
Copy link
Member

@brunobertechini did you manage to reproduce this?

@MarcinHoppe
Copy link
Contributor

I am closing this issue for now because we don't have any new information that would allow us to get any closer to reproducing this.

@brunobertechini Don't hesitate to re-open this issue if you have more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants