Hello Halil,
First of all, sorry for the long post, but Im stuck with this.
Im trying to use Abp infrastructure inside a NServiceBus Endpoint and I am having problems with unitofwork.
NServiceBus handle its own transaction and unitofwork when consuming a message and invoking a given handler. (<a class="postlink" href="http://docs.particular.net/nservicebus/pipeline/unit-of-work">http://docs.particular.net/nservicebus/ ... it-of-work</a>)
Inside this handler I am injecting few repositories. Think the Handler as more like a appservice triggered by a message received.
The problem is I cant get control over Abp unitofwork to be able to complete the transaction only after nservicebus has finished working with the message.
The approaches suggested in documentation (<a class="postlink" href="http://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work">http://aspnetboilerplate.com/Pages/Docu ... it-Of-Work</a>) did not work for this specific case.
I really need your help to move forward.
This is the handler code which is instantiated by NServiceBus when a new message is received:
public class CreditGenerationApprovalHandler : IHandleMessages<ApproveCreditGeneration>
{
public IBus Bus { get; set; }
public IRepository<Credit, Guid> CreditRepository { get; set; }
public void Handle(ApproveCreditGeneration message)
{
Credit credit = CreditRepository.Get(message.CreditId.Value);
credit.Approve();
Bus.Publish<CreditGenerationApproved>(evt =>
{
evt.CreditId = credit.Id;
evt.CreditValue = credit.Value;
});
}
}
I have integrated the IoC and bootstrapped Abp like this (this is called by NServiceBus upon initialization):
public class AbpBootstrap : INeedInitialization
{
public void Customize(BusConfiguration configuration)
{
// Initialize Abp infrastructure
var bootstrapper = new AbpBootstrapper();
bootstrapper.IocManager.IocContainer.AddFacility<LoggingFacility>(f => f.UseLog4Net().WithConfig(ITSConsts.Log4NetConfigFile));
bootstrapper.Initialize();
}
}
NServiceBus IoC is using Abp Windsor:
// Retrieves current IocContainer from Abp
var container = IocManager.Instance.IocContainer;
// Configure Container into NServiceBus
configuration.UseContainer<WindsorBuilder>(c => c.ExistingContainer(container));
If I don't configure anything, the transaction is aborted at the following method (which is what the documentation states, the method is atomic, it completes the transaction right after its execution):
Credit credit = CreditRepository.Get(message.CreditId.Value);
I cannot work that way because I need to perform other tarnsactional operations like Bus.Publish (MSMQ transactional queue).
If I decorate the Handle method with [UnitOfWork] the handler is not able to call it (can't figure why).
Another approach I have tried is using the IManageUnitsOfWork control for NServiceBus (which I believe I should disable Unitofwork at the handle method) and let NSB control it like :
public class EfUnitOfWorkManager : IManageUnitsOfWork, INeedInitialization
{
public ILogger Logger { get; set; }
public IUnitOfWorkManager UowManager { get; set; }
private IUnitOfWorkCompleteHandle _unitOfWork;
public void Customize(BusConfiguration configuration)
{
configuration.RegisterComponents(config =>
{
config.ConfigureComponent<EfUnitOfWorkManager>(DependencyLifecycle.InstancePerCall);
});
}
public void Begin()
{
Logger.Debug("NsbUnitOfWorkManager started.");
_unitOfWork = UowManager.Begin();
}
public void End(Exception ex = null)
{
if (ex == null)
{
Logger.Debug("NsbUnitOfWorkManager completed.");
UowManager.Current.SaveChanges();
}
else
{
Logger.Error("NsbUnitOfWorkManager failed.", ex);
}
}
}
Are there any possibilities to disable the commit trnsaction and let me do it manually like mentioned above at the End method called by NServiceBus ?
Many thanks in advance
Bruno