I am writing this post here in hopes that someone can help me out.
I am trying to implement NServiceBus
on an ASP.NET MVC application. I have gone through each and every step to ensure that everything is wired up right. I have an event that passes a Job Id to my handler which then performs a Linq-to-Sql query and looks up a job and then emails an alert. The process is very simple.
However, I cannot for the life of me get MSDTC to work. I keep on getting the following error:
Here is how I have my Bus configured:
Bus = NServiceBus.Configure.WithWeb()
.Log4Net()
.DefaultBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(false)
.PurgeOnStartup(false)
.UnicastBus()
.ImpersonateSender(false)
.CreateBus()
.Start();
I am not using Transactions so I know for a fact that MSDTC should not even be called.
My Handler code is as follows:
public void Handle(ApplyJobMessage message)
{
if (message != null)
{
using(var context = new MyContext())
{
JobPosting posting = (from c in context.JobPostings
where c.JobPostingId == message.JobId
select c).SingleOrDefault();
}
The endpoint is configured as follows:
public class MessageEndpoint : IConfigureThisEndpoint, AsA_Server, IWantToRunAtStartup
Everything works great. The message arrives correctly when I do:
Bus.Send(message);
However, the MSDTC error occurs as shown:
2011-01-20 00:55:09,744 [Worker.5] ERROR NServiceBus.Unicast.UnicastBus [(null)]
<(null)> - JobApplicationHandler Failed handling message.
System.Runtime.InteropServices.COMException (0x8004D02A): The MSDTC transaction
manager was unable to push the transaction to the destination transaction manage
r due to communication problems. Possible causes are: a firewall is present and
it doesn't have an exception for the MSDTC process, the two machines cannot find
each other by their NetBIOS names, or the support for network transactions is n
ot enabled for one of the two transaction managers. (Exception from HRESULT: 0x8
004D02A)
at **System.Transactions.Oletx.ITransactionShim.Export**(UInt32 whereaboutsSize,
Byte[] whereabouts, Int32& cookieIndex, UInt32& cookieSize, CoTaskMemHandle& coo
kieBuffer)
at System.Transactions.TransactionInterop.GetExportCookie(Transaction transac
tion, Byte[] whereabouts)
2011-01-20 00:55:09,749 [Worker.5] WARN NServiceBus.Unicast.Transport.Msmq.Msmq
Transport [(null)] <(null)> - Failed raising 'transport message received' event
for message with ID=9cb4b136-e110-4b87-81f6-ee4cd3fcaf46\6151
System.Reflection.TargetInvocationException: Exception has been thrown by the ta
rget of an invocation. ---> System.Transactions.TransactionManagerCommunicationE
xception: Communication with the underlying transaction manager has failed. --->
System.Runtime.InteropServices.COMException (0x8004D02A): The MSDTC transaction
manager was unable to push the transaction to the destination transaction manag
er due to communication problems. Possible causes are: a firewall is present and
it doesn't have an exception for the MSDTC process, the two machines cannot fin
d each other by their NetBIOS names, or the support for network transactions is
not enabled for one of the two transaction managers. (Exception from HRESULT: 0x
8004D02A)
at System.Transactions.Oletx.ITransactionShim.Export(UInt32 whereaboutsSize,
Byte[] whereabouts, Int32& cookieIndex, UInt32& cookieSize, CoTaskMemHandle& coo
kieBuffer)
at System.Transactions.TransactionInterop.GetExportCookie(Transaction transac
tion, Byte[] whereabouts)
--- End of inner exception stack trace ---
at System.Transactions.TransactionInterop.GetExportCookie(Transaction transac
tion, Byte[] whereabouts)
at System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transacti
on transaction, Byte[] whereAbouts)
at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transa
ction)
at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transacti
on transaction)
at S开发者_开发问答ystem.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection ownin
gObject)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection ow
ningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection ou
terConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionU
ser user)
at System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe()
at System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode()
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider
.Execute(Expression query)
at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Express
ion expression)
at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source)
I have tried DTC ping and it successfully works so I know for a fact that MSDTC isn't the issue. I have read that NHibernate had similar issues with NServiceBus but I haven't been able to draw any parallels on the same with LINQ to SQL.
Any help on this matter would be very appreciated.
The accepted solution is really a workaround for the problem. I'll suggest you to use DTCPing tool to set up MSDTC properly and find the underlying problems.
Check out this posts for more information:
- Troubleshooting MSDTC issues with the DTCPing tool
- Conquering NServiceBus part 5 – Troubleshooting DTC
- Troubleshooting MSDTC, RPC and NServiceBus issues
MSDTC is quite obscure, good luck!
I had a similar issue and found that the cause was more LINQ-to-SQL than NServiceBus. If you look at your stack trace you'll see the root cause is your LINQ and SqlClient libraries, not NSB. The solution that I ended up using, which may or may not work for you depending on how important it is for your data access to be transactional, was to explicitly turn off transactions in my LINQ to SQL code. In my case, I was simply calling a stored procedure using LINQ to SQL, with code like this:
public void Save(SomeEvent someEvent)
{
using (new TransactionScope(TransactionScopeOption.Suppress))
{
_loggingDatabaseConnection.DataContext.log_ClickInsert(
someEvent.LogDate,
someEvent.Id,
someEvent.OtherStuffGoesHere);
}
The important part here is the TransactionScope and TransactionScopeOption.Suppress. This ensures LINQ to SQL doesn't try to enlist the call into a transaction using the DTC. This is working in my solution in my message handler (NServiceBus Generic Host).
What I notice is that you're configuring NServiceBus as a server, which means that it is transactional. I think what you have here is a non-transactional web app which is sending messages to a transactional server.
I can remember having issues myself with MSDTC, but for the life of me can't find the blogs/posts/whatever I referenced to solve the issue. Anyway, if that ping program is working it is a bit weird. One suggestion I may add is trying to add the line,
.RunCustomAction(() =>
NServiceBus.Configure.Instance.Configurer.ConfigureProperty<MsmqSubscriptionStorage>(
msg => msg.DontUseExternalTransaction, true))
just before the .CreateBus()
line. If you are using subscriptions this will tell the subscription to stop using transactions, which may be your problem. However be warned doing this will therefore make your subscriptions less reliable, so don't use it in critical situations.
精彩评论