Somewhat OT: Network DTC

Somewhat OT: Network DTC

Old forum URL: forums.lhotka.net/forums/t/2400.aspx


ajj3085 posted on Wednesday, February 21, 2007

Hi all,

I have a BO which represents a contact.  There's a flag on this contact indicating if the contact wants to receive email notifications from us.  The notifications are handled by Notification Services.

As part of the DataPortal_Update, I check if that flag has changed, and if it has, I use the NS API to update the subscriber / subscription data in NS.  I've found I can include these updates within my TransactionScope transaction, but the problem is that DTC isn't allowing network access.  I'm getting this error:  System.Transactions.TransactionManagerCommunicationException: Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool.

Now, I did go in to the Componet Services tool and on the MSDTC table and checked the appropriate boxes to enable network transactions (except IP transactions) on both the db server and the client machine.  However, I still get this error.  Anyone see what I'm missing?

Another thing... should I just start using remoting?

Thanks
Andy

ajj3085 replied on Thursday, February 22, 2007

Anyone have any ideas on this?

As a workaround I found I can start using remoting and then DTC happens on the db server... but that's a bigger change to my application than setting up DTC properly (I haven't been testing remoting configurations thus far).

Thanks

RockfordLhotka replied on Thursday, February 22, 2007

XP SP2 disabled this. There's a KB article on how to turn it back on - which is a multi-step process.

http://www.lhotka.net/weblog/ReenablingMSDTCUnderWinXPSP2.aspx

btw, I found this using the search page at http://www.lhotka.net/Search.aspx, which uses either google or live.com to search my entire domain - invaluable resource for searching the forum, my blog, etc.

ajj3085 replied on Thursday, February 22, 2007

Ok,

I don't know why, but I tried this, and it works on my local machine when the DB and NS instance are on the development server. 

However, its not working on a Virtual PC that I have setup with just a basic WinXP SP2 install + the needed components (NS client, .Net framework, etc).

I guess I'll have to hunt down an actual PC to see if the DTC is failing because of the virtual machine or if its working because of some other setting on my computer.

Thanks
Andy

ajj3085 replied on Friday, February 23, 2007

I think I have this working.

It seems that you need to enable both Inbound and Outbound transactions on both client and server, although the steps I followed seemed to indicate that I could have the client with Outbound only and the server Inbound only.  Perhaps I'm not understanding how DTC is working though.

ItsDubC replied on Thursday, March 01, 2007

I followed the Microsoft KB article to re-enable MSDTC and applied it to both the application server and the db server.  I also enabled both inbound and outbound on both, but I am still getting the same error message: 

System.Transactions.TransactionManagerCommunicationException: Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool. ---> System.Runtime.InteropServices.COMException (0x8004D024): The transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D024)

Seems to be erroring out in a child object's Insert routine when I start a transaction.  I'm using NHibernate to persist my objects but that seems to be unrelated to this issue.  Why MSDTC isn't working is beyond me.  Were there any other settings in the MSDTC Security Configuration that you changed besides the inbound/outbound settings?

ajj3085 replied on Friday, March 02, 2007

Check out the link that Rocky posted; you also need to ensure that the firewalls on both client and server allow MSDTC.exe and port 135 I believe.. check the article for the correct information.

ItsDubC replied on Friday, March 02, 2007

Ya I added those entries to Windows Firewall as well and it still wasn't working.  But in doing more searching on this forum, I realized that my parent and child objects were starting their own transactions instead of having just the parent start it and having the child execute from within that one.  I changed my code around a bit and it seems to be working well so far.  Thanks for the help.

kbe replied on Tuesday, March 13, 2007

I am having similar issues with my web hosting company.  They relate that MSDTC is on for the webserver, but not the SQL server.  Once they get that going, I am concerned that my code may be spawning wayward children as well -- I have wrapped a transaction around vb.net 2.0 tableadapters, which I believe create their own execution.  It works fine on my local hosted web/sql server (same machine).  Did you use the same approach and have to fix the code?  If so, what choices did you make to fix your code?  Thanks for the further insight.

RockfordLhotka replied on Tuesday, March 13, 2007

If you are only updating a single database (even multiple tables) then you probably do NOT want the DTC involved, as it is just a performance hit.

Instead, you want "local transactions", which you can get by using ADO.NET transactions directly, or using System.Transactions. Either way, you need to ensure you only open one database connection per root object (and its children).

This is the primary reason I added AppliationContext.LocalContext to CSLA .NET version 2.1, because LocalContext gives you an easy way to open a connection in your root object, and make it available to all your child/grandchild/etc. objects during the update process.

I show how to do this in the CSLA .NET Version 2.1 Handbook, but you can probably visualize the approach. In your root object open the connection, put the connection value into LocalContext. Then in each child, get the connection from LocalContext and use it to do your updates. Back in the root object, once all calls to child objects are complete (typically at the end of your using statement), remove the connection from LocalContext.

Using this technique with either Manual or TransactionScope transactions will avoid the need for the DTC. The result is higher performance and simpler administration of your app, and is the way to go unless you are talking to more than one database within your transaction.

William replied on Wednesday, March 14, 2007

Hi,

This is related to transaction handling.

I am creating a reusable business object library with CSLA, which is to be used by a number of applications. Some of these applications will only connect to SQL Server databases; some will connect to SQL Server databases as well as other databases, e.g. Oracle running on Unix machine.

To ensure data integrity, I used TransactionScope attribute on DataPortal_Insert and DataPortal_Update methods so that transaction handling is transparent and "automatically integrated" (through tx promotion) into the client applications.

This looks like somehow restricts the deployment model and requirements for the client applications? e.g. MSDTC requirements, Windows OS, etc.?
What do you suggest to make this reusable class library truely reusable and flexible enough for its intended purpose?

Please advise.

Regards,
William

RockfordLhotka replied on Wednesday, March 14, 2007

Two things to keep in mind:

  1. As I mentioned previously, you can take steps to avoid the use of the DTC
  2. If you use an application server (remote data portal), then even if you DID use the DTC it would be used on the server, not the client, so the client would be blissfully unaware of that complexity

 

Skyguard replied on Tuesday, May 27, 2008

RockfordLhotka:

If you are only updating a single database (even multiple tables) then you probably do NOT want the DTC involved, as it is just a performance hit.

Instead, you want "local transactions", which you can get by using ADO.NET transactions directly, or using System.Transactions. Either way, you need to ensure you only open one database connection per root object (and its children).

This is the primary reason I added AppliationContext.LocalContext to CSLA .NET version 2.1, because LocalContext gives you an easy way to open a connection in your root object, and make it available to all your child/grandchild/etc. objects during the update process.

I show how to do this in the CSLA .NET Version 2.1 Handbook, but you can probably visualize the approach. In your root object open the connection, put the connection value into LocalContext. Then in each child, get the connection from LocalContext and use it to do your updates. Back in the root object, once all calls to child objects are complete (typically at the end of your using statement), remove the connection from LocalContext.

Using this technique with either Manual or TransactionScope transactions will avoid the need for the DTC. The result is higher performance and simpler administration of your app, and is the way to go unless you are talking to more than one database within your transaction.

Thank you!!! - this is the right answer (of course) - even though I'm using a different (non-CSLA) framework on the project I'm working on right now, this fixed my problem - one line of code was calling and using a different connection... All other suggestions from Google, recommended to turn on MSDTC (which I now is not the correct answer)... this thread helped me solve my problem... Thanks!

Copyright (c) Marimer LLC