.NET Forum / .NET Framework / New Users / May 2005
Distributed Transactions and System.EnterpriseServices
|
|
Thread rating:  |
Francois Malgreve - 06 May 2005 06:54 GMT Hi dear,
I need to implement Distributed Transactions in my application as it is using 2 SQL servers. I am using windows server 2003, Sql Server 2000 and .Net 1.1.
After a first post and some research on google I have seen that there is a package System.EnterpriseServices part of the .Net framework that interface with COM+ components. It seems to interface with the DTC windows service. My problem is that I have no experience with that package neither with COM+ component.
What I really need is a tutorial of how to implement Distributed Transaction in a software, for exemple, should it be at the Business Layer level (I think so) or can the Data layer take care of that by itself? And also how to achieve it? What is the best design / best practice? For exemple sometimes some business methods can be the root of a transaction but sometimes they can be part of a greater user case, thus be part of an existing transaction.
I have seen some source code with stuff like the following but i simply do not understand it (the attributes in front of the class and methods declaration.). Also note that the class MUST inherit ServicedComponent...
:( Also i do not know if it is flexible enough and resolving an important issue which is some methods may have to initiate their transactions themselves as they are the root of the transaction or using an existing transaction, depending of the use case.
[Transaction(System.EnterpriseServices.TransactionOption.Required)] [ClassInterface(ClassInterfaceType.AutoDispatch)] [ObjectPooling(MinPoolSize=4, MaxPoolSize=4)] // WHAT IS THIS ?? [Guid("14E3573D-78C8-4220-9649-BA490DB7B78D")] public class OrderInsert : ServicedComponent {
...
[AutoComplete] public int Insert(OrderInfo order) {
....
}
}
I am a beginner in Distributed Transaction but I know what is a transaction and i have been using it many times on single DB connection.
I have also seen that the SqlConnection class has a method EnlistDistributedTransaction() but in the sample code I have seen using distributed transaction, it is not using that method but seems to rely entirely on the System.EnterpriseServices and on the "magic" attributes defined in front of the class definition.
Is there someone who has a good idea of where i can find some help / resource / book to help me gain knowledge about Distributed Transaction in general and how to implement it? All I can see from the web are exemples but I would ideally need more than that I need an explanation of how it is implemented and why it is implemented that way and also what options and attributes I can use. Also why objects seems to be pooled... see attribute [ObjectPooling(MinPoolSize=4, MaxPoolSize=4)] Is there anywhere a reference about those attributes?
Best regards and thanks a lot in advance.
Francois Malgreve
Sahil Malik [MVP] - 06 May 2005 07:17 GMT Francois -
That is a lot of questions, let me begin answering them one by one in small digestable peices.
First of all here is how you'd implement distributed transactions -
http://codebetter.com/blogs/sahil.malik/archive/2005/04/11/61755.aspx
Okay so once you go through that, and pick the method most suitable to you, let me know which one you picked
1. wrap in db 2. enterprise services 3. service config 4. system.transactions
And I'll be happy to elaborate further.
- Sahil Malik [MVP] http://codebetter.com/blogs/sahil.malik/
> Hi dear, > [quoted text clipped - 70 lines] > > Francois Malgreve Francois Malgreve - 06 May 2005 09:14 GMT Hi.
Yes it is indeed a lot of question, it most likely reflects my state of ignorance on the subject right now. Anyway I would go for choice [3] ServiceConfig class as I am using Windows 2003 Server.
Tx a lot in advance,
Francois
> Francois - > [quoted text clipped - 92 lines] > > > > Francois Malgreve Sahil Malik [MVP] - 06 May 2005 12:33 GMT Okay great, that makes your life simpler. Here is a sample to do ServiceConfig based Distributed Transaction -
using System;
using System.EnterpriseServices;
namespace SDSample
{
class Class1
{
[MTAThread]
static void Main(string[] args)
{
ServiceConfig config = new ServiceConfig();
config.Transaction = TransactionOption.Required;
ServiceDomain.Enter(config);
try
{
MyTxCode();
}
catch(Exception e)
{
// we got an exception
Console.WriteLine(e.Message);
// so, we should abort the transaction
ContextUtil.SetAbort();
}
finally
{
ServiceDomain.Leave();
}
}
// The code that I want to be transactional
static void MyTxCode()
{
Console.WriteLine(ContextUtil.TransactionId);
// Open connection to database 1
// Execute update in database 1
// Open connection to database 2
// Execute update in database 2
}
}
}
BTW - I'd be more than happy to guide you through the rest of the options, plus say how the above is different from a single database transaction, but just ask me small, peice-meal and specific questions.
- Sahil Malik [MVP] http://codebetter.com/blogs/sahil.malik/
> Hi. > [quoted text clipped - 118 lines] >> > >> > Francois Malgreve Francois Malgreve - 06 May 2005 13:26 GMT Ok,
Tx a lot for your reply. I've got 3 questions that pops up in my mind right away
1. I assume that after the line MyTxCode(); you should have ContextUtil.SetComplete right? 2. Why your class does not inherit from ServiceConfig class? In the examples I have seen on the net, all the classes that need to support DTC inherits from the ServiceConfig class. What is the difference between inheriting from ServiceConfig and not inherit from it? Also it seems that it is possible to use DTC in a quite different way depending you have win 2003 or not. Is that related with my question? 3. What other options are you speaking about? :p
I hope you do not mind i ask you more questions about all of that.
Tx a lot. (not "Transactions a lot", but rather "Thanks a lot" :p)
Best regards,
Francois.
> Okay great, that makes your life simpler. Here is a sample to do > ServiceConfig based Distributed Transaction - [quoted text clipped - 206 lines] > >> > > >> > Francois Malgreve Francois Malgreve - 06 May 2005 13:30 GMT Also your solution is close to what I have seen on:
http://blogs.msdn.com/florinlazar/archive/2004/07/24/194199.aspx
But it seems that this kind of approach brings some problems, see the comment of Marcelo Lavio .
Tx again.
Francois.
> Ok, > [quoted text clipped - 239 lines] > > >> > > > >> > Francois Malgreve Sahil Malik [MVP] - 07 May 2005 03:08 GMT It isn't similar - because that is where I copy pasted from :)
Regards Marcelo's comment - again the isolation level is a "suggestion" - whether or not the RM listens to that suggestion depends on the RM and it's mood and the stars direction and wind temperature (well not quite - but you get my point - depending upon the exact RM there might be some logic involved).
System.Transactions is VERY similar - just better. Now specifically SQLConnection, you can specify a lower isolation level - and as long as there is one non durable RM involved or two non durables in the same appdomain - the transaction is maanged by LTM - Lightweight transaction manager. Soon as a second RM in a different appdomain or a nondurable RM comes into the picture, a phenomenon called promotable enlistment occurs - in which the transaction is handed over to the MSDTC for 2 phase commits - which means the isolation levels are bumped up to serializable. Now I have gotten conflicting emails from people suggesting that even in a distrib. transaction the isolation levels are not serializable - but per my tests that is just not true. Per my tests, isolation levels do get bumped up to Serializable (there were locks on the rows, and deadlocks were auto detected).
I might add that promotable enlistment needs Yukon/Sql2k5.
Your alternative is to either write your own RM or to wrap the distributed transaction within the database.
- Sahil Malik [MVP] http://codebetter.com/blogs/sahil.malik/
> Also your solution is close to what I have seen on: > [quoted text clipped - 270 lines] >> > >> > >> > >> > Francois Malgreve Pablo Castro [MS] - 12 May 2005 03:38 GMT An additional detail (and now we're going deep into details): DTC is actually not involved when the first RM comes into the picture if that RM supportes single-phase enlistments (or "delegation"), for example, ADO.NET+SqlClient supports it when connected to a SQL Server 2005 server. That means that even with 1 persistent RM you still avoid the DTC overhead. When a second persistent RM comes into the picture, then a second thing, "promotion", happens, which is where we pull DTC into the picture. If the first persistent RM does not support delegation, then we hook up with DTC right away.
 Signature Pablo Castro Program Manager - ADO.NET Team Microsoft Corp.
This posting is provided "AS IS" with no warranties, and confers no rights.
> It isn't similar - because that is where I copy pasted from :) > [quoted text clipped - 303 lines] >>> > >> > >>> > >> > Francois Malgreve Sahil Malik [MVP] - 07 May 2005 03:03 GMT Hey Man,
Really sorry, I've been tied up all day - hence the delay in answers. Anyway, here I am -
To answer your questions -
1. Not necessary - but you could add it for clarity. 2. Well inheriting from ServiceConfig was the original Enterprise Services way. It sucked in a number of ways, assemblies had to be strongly named, they had to be put in GAC - debugging them was a pain. So folks devised new ways of doing distributed transactions without having to inherit (and what if you needed to inherit from something else?) 3. The other options are what I just described in point #2 - which is the more portable way to do it in .NET 1.1/1.0 - it doesn't have OS restrictions. But the most awesome way to do Distributed transactions is to use the System.Transactions namespace - .NET 2.0 only. What that will let you do is, you can enlist multiple RMs (resource managers), and they will enlist themselves in the distributed transaction. The way it is implemented is quite elegant frankly - you suggest an isolation level, but the RM may or maynot listen. The best part is something called as promotable enlistment, and another hella cool thing is that you can write your own RMs. All of this is detailed out very nicely over here - http://www.codebetter.com/blogs/sahil.malik/archive/2005/04/28/62604.aspx
More questions? :-)
- Sahil Malik [MVP] http://codebetter.com/blogs/sahil.malik/
> Ok, > [quoted text clipped - 247 lines] >> >> > >> >> > Francois Malgreve Francois Malgreve - 09 May 2005 11:20 GMT Hi,
Thanks a lot for your answers. I think that I start to more or less get it.
As I do not have the luxury to use .Net 2.0, I can either: 1. Chose to follow the MS design and derive my class from ServicedComponent. That should be easy as I can follow the doc on MSDN to do that. But the drawback is that i need to sign my components and register them in COM+. A good point is that it will work for Win 2000 too, not only 2003 2. Use the COM+ ServiceConfig class without deriving from ServicedComponent but does it always work well? Is it used in production environment? Is it solid? Also it is limited to Windows 2003 only.
My production server will be 2003, then that is not the problem.
My only problem is to make the choice between 1. and 2. I would prefer to go for 2 but ONLY if I can trust it and if it is a proven solution that I can bring in production without any problems. It needs to be solid and work well under an heavy load. I do not want to discover problems when it will be too late. My project dead line is soon then I have to make the right choice very soon and stick to it. I hope you can give me your opinion to pick up the right choice. If choice 2 is proven and work well in lives applications (not just proof-of-concept demo) then I would go for it.
Thanks a lot again, you have been more than helpfull
Francois.
> Hey Man, > [quoted text clipped - 161 lines] > >> >> > >> >> First of all here is how you'd implement distributed transactions - http://codebetter.com/blogs/sahil.malik/archive/2005/04/11/61755.aspx
> >> >> Okay so once you go through that, and pick the method most suitable to > >> > you, [quoted text clipped - 57 lines] > > existing > >> >> > transaction, depending of the use case. [Transaction(System.EnterpriseServices.TransactionOption.Required)]
> >> >> > [ClassInterface(ClassInterfaceType.AutoDispatch)] > >> >> > [ObjectPooling(MinPoolSize=4, MaxPoolSize=4)] [quoted text clipped - 46 lines] > >> >> > > >> >> > Francois Malgreve Sahil Malik [MVP] - 10 May 2005 02:30 GMT Distributed Transactions are never as good as local transactions are never as good as non-transactional
Well .. good referring to .. performance etc.
But they do guarantee "transactional behavior" which is what you're after.
Just know the baggage a transaction brings along with it.
BTW (I thought this was gonna be a one liner, but u got me started yet) - let me supplant my argument with an example.
You've visited an ATM right? That is the classic example of Debit/Credit/Cash Withdrawl/Deposit - all in one transcaction? That's complete bull cra!p. Because in reality, no sane bank will implement a transaction around that.
Why? Because considering how far their computer systems are, considering how unreliable the networks can be - that would be a nightmare to resolve.
So what do they do? Logging and Auditing - and sanity checks the next morning. With enough logged information for an atomic rollback.
Two phase commits (transactions) are never the ONLY right answer :-) .. just one of the possibilities.
Think 'bout it !!
- Sahil Malik [MVP] http://codebetter.com/blogs/sahil.malik/
> Hi, > [quoted text clipped - 337 lines] >> >> >> > >> >> >> > Francois Malgreve Francois Malgreve - 10 May 2005 05:17 GMT Well,
I agree with you and I think that logging and auditiing are always a good thing to do. Also sanitary check is something that may be needed in some case. I will think about that too.
Anyway I still need to do Distributed Transactions and I still need to make a choice between make all my transacted classes inherit from ServicedComponent or then use ServiceConfig. Have you ever used ServiceConfig in a real application? Or know anyone who did it?
If I have no more guarantee about using ServiceConfig I will have to use ServicedComponent.
Francois.
> Distributed Transactions are never as good as local transactions are never > as good as non-transactional [quoted text clipped - 94 lines] > > this > >> is detailed out very nicely over here - http://www.codebetter.com/blogs/sahil.malik/archive/2005/04/28/62604.aspx
> >> More questions? :-) > >> [quoted text clipped - 268 lines] > >> >> >> > > >> >> >> > Francois Malgreve Sahil Malik [MVP] - 10 May 2005 05:52 GMT > I agree with you and I think that logging and auditiing are always a good > thing to do. Also sanitary check is something that may be needed in some > case. I will think about that too. I think you meant "Sanity Check" :-) HEEHEE
Anyway, I have not used ServiceConfig because I could not restrict my application to the OS it needs. I have used ServicedComponent/MTS/MSDTC otherwise. But I really don't think ServiceConfig is any worse than ServicedComponent performance viz.
- Sahil Malik [MVP] http://codebetter.com/blogs/sahil.malik/
> Well, > [quoted text clipped - 433 lines] >> >> >> >> > >> >> >> >> > Francois Malgreve Francois Malgreve - 10 May 2005 09:53 GMT I was not speaking abotu performance but more about if it is bug free and can be used in production evironment. It seems that in the Microsoft doc they do not mention this way to do, except if i missed it. Sometimes, even when an API is available it is not always recomended to use it in some ways. As it is not designed for it and as it could bring unexpected behavior. Now I may just be over worrying and I should just go for the ServiceConfig option. I am just looking for an advise from a Senior person like you.
Thanks a lot again,
Francois
> > I agree with you and I think that logging and auditiing are always a good > > thing to do. Also sanitary check is something that may be needed in some [quoted text clipped - 143 lines] > >> > this > >> >> is detailed out very nicely over here - http://www.codebetter.com/blogs/sahil.malik/archive/2005/04/28/62604.aspx
> >> >> More questions? :-) > >> >> [quoted text clipped - 297 lines] > >> >> >> >> > > >> >> >> >> > Francois Malgreve Sahil Malik [MVP] - 10 May 2005 12:01 GMT Senior? BWAHAHAHAH :-). I'm just another guy like you :-)
Anyway, Well you'd really never find out unless you just went ahead and implemented it. Thats what we call Live and Learn.
Do share your experience though so others can learn from you (myself included). If you want, just send me a message through my blog and I'll be happy to post it on my blog (so everyone can benefit from it).
- Sahil Malik [MVP] http://codebetter.com/blogs/sahil.malik/
>I was not speaking abotu performance but more about if it is bug free and > can be used in production evironment. It seems that in the Microsoft doc [quoted text clipped - 513 lines] >> >> >> >> >> > >> >> >> >> >> > Francois Malgreve Florin Lazar [MSFT] - 21 May 2005 03:46 GMT Francois,
ServiceDomain/ServiceConfig is a well supported feature as much as ServicedComponent is. The newsgroup dedicated to them is microsoft.public.dotnet.framework.component_services
Regards,
 Signature Florin Lazar - Microsoft - [ http://blogs.msdn.com/florinlazar ] Please do not send email directly to this alias. This alias is for newsgroup purposes only. This posting is provided "AS IS" with no warranties, and confers no rights.
Well,
I agree with you and I think that logging and auditiing are always a good thing to do. Also sanitary check is something that may be needed in some case. I will think about that too.
Anyway I still need to do Distributed Transactions and I still need to make a choice between make all my transacted classes inherit from ServicedComponent or then use ServiceConfig. Have you ever used ServiceConfig in a real application? Or know anyone who did it?
If I have no more guarantee about using ServiceConfig I will have to use ServicedComponent.
Francois.
Sahil Malik [MVP] - 10 May 2005 02:36 GMT Incidentally, your question sparked enough interest in my head that I posted it on my blog - http://www.codebetter.com/blogs/sahil.malik/archive/2005/05/09/62986.aspx
:) - Sahil Malik [MVP] http://codebetter.com/blogs/sahil.malik/
> Hi, > [quoted text clipped - 337 lines] >> >> >> > >> >> >> > Francois Malgreve Raphael Renous[MSFT] - 06 May 2005 19:21 GMT It may not be relevant to your environment, but .Net 2.0 introduce System.Transaction, a new namespace that will let you do create distributed transactions without having to use COM+ or EnterpriseServices.
There are some good blogs around System.Transaction: http://pluralsight.com/blogs/jimjohn/ http://blogs.msdn.com/florinlazar/
Raphael Renous[MSFT]
> Hi dear, > [quoted text clipped - 70 lines] > > Francois Malgreve
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|