Posts

Showing posts from 2011

Shocker! - Do not use Environment.MachineName

I first found this article after I got an issue:  http://blogs.msdn.com/b/brada/archive/2005/08/10/449767.aspx Let me go around to clarifying this further, and how I re-verified this issue http://msdn.microsoft.com/en-us/library/system.environment.machinename.aspx MSDN clarifies that this is NETBIOS name. http://en.wikipedia.org/wiki/NetBIOS Wikipedia clarifies that NETBIOS name has 16 characters, but Microsoft uses only 15 characters for the same. http://msdn.microsoft.com/en-us/library/system.net.dns.gethostname.aspx This is what should be used.

Living with Windows Driver woes

One of my colleagues used to work for MS before and his job was to look at the windows crash logs and determine what went wrong. Most of the time, he used to find out that it was a problem with the processor or the drivers for some hardware components. As anyone who has ever tried to host servers by themselves know, it is critical to keep them updated so that the PC works fine. Especially when developers like us install 2008 R2 on a laptop and sometimes not all the drivers get installed properly. Windows Update does not always show missing or out of date drivers. Do the following which might surprise you: 1) Go to http://www.driverdetective.org/  and install their software. Do not install Norton with it. 2) Scan your laptop/ desktop/ server. 3) In most cases you will find some drivers out of date or not even installed. I saw this with a brand new server from Dell which did not have the chipset drivers installed. Once you find what is out of date or missing, it is easy to se

Using Visual Studio Remote Debugger between servers in different domains

Sometimes, you might want to use the visual studio remote debugger between 2 servers - one in the domain, and the other outside it. Usually, if you try to do this, it will error out saying that the machine outside the domain cannot connect to your machine. Even if you try to put the credentials in the control panel - users area it will still not work. Well, you know that the remote debugger itself has an option for debugging without authentication. What I did not know was that Visual Studio 2010 SP1 can also debug without authentication. Just open the top combo box to see another option, if you select it, it will now let you debug, although note that this is not secure, so use this warily. Remember to first go to the server where you want to debug and open the remote debugger > Tools > Options > No Authentication, and Allow any user to debug. Then select transport as Remote (Native only with no authentication) in VS and the qualifier is the remote server name. The

Keeping your original WCF config file and making it run in Azure as a worker role

If you get 405 errors while trying to access the WCF service with GET enabled in the config file, note that you will need to modify the config file behaviors area right next to where you enable httpget to the DNS name of the azure deployment: x.cloudapp.net Otherwise, no matter what you do, you will not be able to get the browser to access the WCF URL. This is when you have HTTP end points for the WCF service with internal endpoint of azure. if  (!InAzureCloud && !InAzureEnvironment) {  return ; } RoleInstanceEndpoint externalEndPoint =  RoleEnvironment .CurrentRoleInstance.InstanceEndpoints[ "EndPoint" ]; Configuration  appConfig =  ConfigurationManager .OpenExeConfiguration( ConfigurationUserLevel .None); ServiceModelSectionGroup serviceModel =  ServiceModelSectionGroup .GetSectionGroup(appConfig); ServicesSection servicesSection = serviceModel.Services;              var  serviceElement = ( from  System.ServiceModel.Configuration. ServiceElement  p  in  se

Handling "System.ServiceModel.AddressAlreadyInUseException: HTTP could not register URL" Exception in Compute Emulator with Windows Azure SDK 1.5

The only other post I found online does not properly explain how to fix this issue: http://blogs.msdn.com/b/avkashchauhan/archive/2011/10/03/handling-quot-system-servicemodel-addressalreadyinuseexception-http-could-not-register-url-quot-exception-in-compute-emulator-with-windows-azure-sdk-1-5.aspx Just go to your app.config file, and in the binding tag for all the services, specify: hostNameComparisonMode = " Exact " For custom bindings, this can be specified as shown below: < customBinding >         < binding >           < httpTransport  h ostNameComparisonMode = " Exact "  /> </binding> </customBinding>

Understanding Microsoft Software

Sometimes it is necessary to understand how MS as a company is moving forward to get an idea about the best way to go forward with your code at the high level. I have already explained in another post how MS badly screwed up for a long time, because of their monopoly and they felt that they could reuse everything they had already built in future products. After the iPhone, they probably realized that they would die if they continued to hoist Windows Mobile 6.5 on consumers. Once the iPod touch was released and it was a bug hit, they started a change in the way they developed new products. It started with the Zune, where they built the OS for that mostly from a fresh, clean slate, and that became a success (w.r.t MS products), and they have followed the same principle for Windows Phone 7 as well. Just because there is something like MS Enterprise Library does not mean that we should batter our code with it, or integrate with it, especially now that it is a monster with several hun

Some .NET Gotchas

1) For.. Each vs For... I have often wondered what is the difference between for..each and for loops in iterating over collections, because I always use the regular for loops. Today, I found out one major difference - if while iterating over the for..each, I add an item to the list being iterated, the for.. each loop will not go over this newly added item. On the other hand, if I use a regular for loop using the length of the collection, and I add an item to the list, it will also get iterated over. 2) Using LINQ and unexpected behavior... For whatever reason, I am observing that if I use LINQ to find an item from a collection, and later I check to see whether the original collection contains this item, then it always returns false. 3) Using Generic Lists I was very surprised to see that, sometimes .Contains() does not work properly, I have to use Exists() and then write a delegate to check for the existence. The same problem manifests when removing an item from the list

ASP.NET Woes

I might have mentioned in the past a case where asp.net does not use the latest code no matter what you try, and the only way I made it work was to compile in debug mode, deploy those dlls and reload the site. Well, I found out one more case today. This can happen if you massively change web.config also. No matter what you try, if your codebase is big enough, it will not use the latest configuration. You can try iisreset, reboot or even deleting the temporary internet files from the .NET folders within the system folder. The only way to get this to work is to set debug="true" in the web.config file and even then, it takes some time for this to take effect.

Kindle 3 Review

I wanted to buy a tabler/ ereader because I read a lot of tech news both from todayamerican and from other sites. It was getting too difficult to read on the iphone and the ipad 2 was very expensive. Eye strain was a problem and so I got the very decentlly priced Kindle 3 with offers from Best Buy for a bargain price as it was the 3g version. I returned it the next day even though I liked it a lot, because after having a connected experience for so long, it has become very difficult for me to send a static PDF to an ereader and tamely read the totally disconnected PDF file. Also, the browser was very very experimental to say the least. The Kindle 3 is an excellent book replacement and nobody who still reads a lot of black and white books will regret purchasing it, but for anybody young, who already reads online blogs and news articles on the web, it will seem too tame. The best word to say is "un-exciting". I think it came too late. 10 years ago, it might have been a

I found something surprising today..

I was seeing this code which was trying to remove an item from a list. This list object was derived from List<T> and did not override the collection based methods. I noticed that the original code did not remove the item from the list even though it tried to: listObject.Remove(listObject.Find(delegate(listItemObject p) { return p.MyProperty == x.MyProperty && p.MyProperty2 == x.MyProperty2; })); This looked fishy, so I changed this code to use LINQ to objects to get a list of items to remove and then I removed the items one by one inside a for loop just to see whether it would work or not. Surprise Surprise! - It did not work. Finally, I had to use the RemoveAll() method passing in this condition as an anonymous method to make the code remove it. I could not understand why it would not remove the item when I called remove on an object which I got from within the list itself.

Cheap TFS hosting

https://www.devindu.com/Solutions/TFS/

What to do when machine IP has changed but your laptop still shows old ip

Pretty simple: ipconfig /flushdns It works most of the time.

Remote debugging in VS 2010

Tried to connect to remote service, debugger did not catch break points even though files were the same! Rebooted all machines, tried again and it worked... Hmm Grrr

Merge friendly refactoring

When moving methods into their own classes, replace them with comments, so the merge will be easy if you need to do it later.

net send in windows 2008 r2

msg /server:server_name <username> press enter type message go to new line press Ctrl + Z to end message press ENTER

Exclude files with a certain extension from list

string invalidExtension = (from p in new List<string>  { ".dll", ".pdb", ".suo", ".docstates", ".ico", ".bmp", ".vs10x", ".vspscc", ".vssscc", ".vsp", ".scc", ".user", ".ctl", ".datasource", ".vsmdi", ".testsettings", ".trx", ".dat" }                             where p == files[i].Extension.ToLower()                            select p).FirstOrDefault(); if (string.IsNullOrEmpty(invalidExtension)) { //Means it has an invalid extension }

The new awesome search engine

Nowadays, I am finding myself using Wolfram Alpha more and more especially in my work day because it can do some really intelligent things like finding the exact number of days between two days or the number of seconds between 2 times. http://www.wolframalpha.com/ This can be really useful!

Pondering over the weird behaviour of w3wp.exe

When my laptop only had 4GB RAM, the process was consuming upto 512MB RAM and also being very slow. Now, when RAM is 8GB, it is fast, but consumes around 155MB RAM. Interesting... Win 2008 r2 x64

When Vista asks you to install search on your 2008 r2 box

Use this link: http://www.nitrix-reloaded.com/2011/03/02/windows-search-4-0-on-windows-server-2008-r2/

Executing a remote process via command line

http://technet.microsoft.com/en-us/sysinternals/bb897553 Such things are useful during the daily life of a developer.

Viewing the debug.writeline output for a windows service

Use this utility:  http://technet.microsoft.com/en-us/sysinternals/bb896647

Best way of finding mac address of local machine

http://www.websofia.com/2011/03/get-local-machines-mac-address-in-c/ I have used a similar technique to iterate through all the network info for the local machine.

Essential Batch File Commands

To stop a windows service: net stop <service name> To kill a process: taskkill /im "<exe name>" To kill a remote process: taskkill /s <server name> /u "<domain>\<user>" /p "<password>" /im "<exe name>" Change Directory: cd "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\" Build a Visual Studio Solution: devenv %devdir%<solution file name> /build Debug Build a solution using MSBUILD: msbuild %devdir%<solution name> /property:WarningLevel=0 /p:Configuration=Debug Copying files to another folder: xcopy %devdir%<project folder>\bin\Debug\*.dll "C:\Program Files (x86)\<folder>\" /y /s /q Starting a Windows Service: net start <service name> Showing "press enter to exit": pause

Error: System.ServiceModel.CommunicationException: The maximum retry count has been exceeded with no response from the remote endpoint. The reliable session was faulted

Found a few references: http://stackoverflow.com/questions/2394084/wcf-the-user-specified-maximum-retry-count-for-a-particular-message-has-been-exc http://consultingblogs.emc.com/pauloreichert/archive/2007/12/14/6081.aspx#9331 http://social.msdn.microsoft.com/Forums/en/wcf/thread/555b47a1-158a-4a42-9b73-d748a4e83b15 http://www.smartasses.be/2009/01/26/wcf-reliable-session-and-keep-alives/ Interesting because I have implemented keep alives for duplex communication earlier. In this case, I tried doing this: <reliableSession inactivityTimeout="23:00:00" maxRetryCount="8192"             ordered="true" />

Having 2 websites share port 80 on IIS

It is fairly easy to do this - while creating the website, specify a different host name. In a dev environment, you can point this host name to 127.0.0.1 in the windows hosts file. Interestingly the mac also has a hosts file which looks similar to the windows hosts file.

Frustrating - selected tab not viewable in VS2010

http://blog.gfader.com/2010/06/vs2010-highlight-selected-tab-in.html - The registry hack is no longer needed. - See the comments in the link to reset the color back.

Windows Form resizing when you change font size for a control at runtime

This seems to be new behavior in .NET 4.0. I found a solution for it, below: http://social.msdn.microsoft.com/Forums/en/vssetup/thread/5a8d1501-1adb-4010-b6d2-c70d69b905f8 In the end, I changed the color of the label to get the effect I wanted.

How to get call stack in C# code

http://www.csharp-examples.net/reflection-callstack/ http://www.csharp-examples.net/reflection-calling-method-name/ This works pretty well.

Dealing with Unity Block in code

It can be a nightmare when every line of code uses unity block and hides the path of code execution unnecessarily. A developer can become quickly overwhelmed trying to figure out how to find out the "real" class whose object is being used. The simplest way is to go to the interface and find references, which will show you all classes which implement the interface. In a bad design, there will always be just one class which implements this interface and which is unnecessarily called via unity. Unity is gr8 - but please use it when plugin is really required.

Making logging async without self destruction

I was initially using the async delegate pattern to make logging asynchronous in the application. The problem is that whether you use this way or thread pool, ultimately, it uses thread pool threads and because everything is busy logging, your application will be slow. Timers may fail to function, and generally, you have lost the advantages of making logging asynchronous. So, I used a pattern I did a few years ago - with a small tweak. Always make error/fatal/warning logs synchronous, for the rest append to a string builder, then use a timer (a single timer) which runs every 1000 ms and which will clear the string builder "buffer" and do whatever you want to do within this. This way, you use minimal thread pool threads, and your logging is still asynchronous enough...

Here is a free code metrics tool

http://blogs.msdn.com/b/camerons/archive/2011/01/28/code-metrics-from-the-command-line.aspx You can use this from the command line by creating a folder, putting the below dlls there and setting this up as a post build event. Useful if you want to get it running without having others install the exe. FxCopCommon.dll FxCopSdk.dll Metrics.exe MetricsReport.xsd Microsoft.Cci.dll Microsoft.VisualStudio.CodeAnalysis.Common.dll Microsoft.VisualStudio.CodeAnalysis.DataflowModels.dll Microsoft.VisualStudio.CodeAnalysis.dll Microsoft.VisualStudio.CodeAnalysis.Interop.dll Microsoft.VisualStudio.CodeAnalysis.Phoenix.dll The post build command line is: $(SolutionDir)folderName\metrics.exe /f:"$(TargetPath)" /o:"$(SolutionDir)folderName\ Reports \$(TargetName).Metrics.xml"

MessageQueueErrorCode -1073741536, Hex Code -0x3FFFFEE0 MSMQ C# .NET 4.0

I got this error on the EndPeek event handler of MSMQ in .NET 4.0 running Visual Studio 2010 on Windows 2003 Server R2. The error shows up as NULL, even though it goes into the MessageQueueException catch. And we find this error code on debugging. Error receiving/ processing MSMQ messages in QueueReceiver, exception: System.Messaging.MessageQueueException (0x80004005)    at System.Messaging.MessageQueue.AsynchronousRequest.End()    at System.Messaging.MessageQueue.EndAsyncOperation(IAsyncResult asyncResult)    at System.Messaging.MessageQueue.EndPeek(IAsyncResult asyncResult)    at OnlineAVL.Services.Core.MessageQueueReceiver`1._receiverMessageQueue_PeekCompleted(Object sender, PeekCompletedEventArgs e) It is more confusing because a simple sample application does not throw this error. I checked everything from project files to compiler and cleaning up code. After debugging for 2 days, I found that the problem is because BeginPeek() is called in a method which is running on

XML serialization woes...

I spent quite some time debugging end of file was reached before parsing could be completed error when casting the body of an MSMQ message object to a byte array. This is an object serialized to XML, and then compressed using .net framework classes. Thought it was a clash between .net 4.0 & 3.5. Nope, turned out that to fix the issue did two things called flush on both serialization and de-serialization, then looked at the entity sent over the wire. The one which failed missed XML include attributes at the class level for some complex properties which were added later. Now works fine. This never gave an error directly. Random errors while de-serialization, so difficult to debug. And was not x64 os problem either ;-)

Interesting Database repercussion for remote applications

You might think that if you have a database server at location X and application servers accessing this database from multiple different locations outside the LAN, it will not affect the DB performance. But that is a wrong assumption. It is not just latency which is a problem for the app servers, your core database operations are also affected by this latency. The reason for this is because the database is transactional and atomic in nature. So if some servers are writing to it, and others are reading from it, then when there is latency over the line, this latency directly affects the lock time of the transactions. This will reduce database speed considerably. So, use web services to send remote requests and let that make a LAN call to the database to reduce this overhead. Then latency is an issue only for the network hop.

Making your application LARGEADDRESSAWARE if it is 32 bit

http://stackoverflow.com/questions/2597790/can-i-set-largeaddressaware-from-within-visual-studio In the post build event: call "$(DevEnvDir)..\tools\vsvars32.bat" editbin / LARGEADDRESSAWARE "$(TargetPath)"

Enable Visual Studio to use more than 2GB of memory

Very useful when you have more memory: http://mkwec.de/2010/01/08/make-visual-studio-use-more-than-2-gig-of-memory/ "Using Visual Studio can be quite frustrating: even having a big quad processor 8 gig SSD raid machine it will still complain not being able to complete an operation because there is not enough “storage” available. Ever seen this “Not enough storage is available to complete this operation.”-Message in large solutions with many projects? Actually this “storage” means memory and you can use the following steps to provide more memory to visual studio: Windows XP users only:  add the /3GB switch to your boot.ini (make sure you backup your old boot.ini before) Windows Vista users only: from the Visual Studio command prompt run: BCEDIT /Set IncreaseUserVa 3072 Apply large address awareness to visual studio by running: editbin /LARGEADDRESSAWARE devenv.exe in your <path-to-VS>/Common7/IDE (make sure you backup your old devenv.exe) Reboot Now Visual Stu

Editing the hosts file on Mac OS/X

It was getting to be a pain to do name resolution while connecting to VPN from a mac. So, here is a link which shows how to add the names and ip address to the hosts file. Interesting that the folder and file name is same as that what windows uses http://decoding.wordpress.com/2009/04/06/how-to-edit-the-hosts-file-in-mac-os-x-leopard/

.LDF file growing too large?

Here is how to shrink it: http://support.microsoft.com/?id=272318 In easy terms, do the shrink, if it does not work, backup the database and do the shrink again! (You might have to change the backup type to Simple from Full).

A WriteThreadSafeCollection implementation

/// <summary>     /// In this class modifying the list is thread safe. To enumerate through the list, always lock the SyncRoot property, otherwise it will not be thread safe. This is the recommended way of making a collection thread safe.     /// </summary>     /// <typeparam name="T">The type of the entity for which the collection is created.</typeparam>     [Serializable]     [DataContract]     public class WriteThreadSafeCollection<T> : Collection<T>     {         private object _syncLock = new object();                public WriteThreadSafeCollection() : base()         {         }           public WriteSynchronizedCollection(IList<T> sourceList) : base()         {             this.AddRange(sourceList);         }            protected override void InsertItem(int index, T item)         {             lock (_syncLock)             {                 base.InsertItem(index, item);             }         }      

VS 2008 breakpoints not hit when you have sp1 and windows 2008 r2 x64 OS

Found the solution to this horrible problem here: http://social.msdn.microsoft.com/Forums/en/vsdebug/thread/f3fcb4fb-8a08-4fa0-8d58-9ed6f3eb1193 The latest Silverlight 3 installer for vs 2008 did not fix the issue fully. I had to install the specific patch from here: http://code.msdn.microsoft.com/KB957912/Release/ProjectReleases.aspx?ReleaseId=1796 Note that if your OS is x64, you need to install the below first: http://www.microsoft.com/downloads/details.aspx?FamilyID=440ec902-3260-4cdc-b11a-6a9070a2aaab

Calling a method using delegates asynchronously

using System.Threading; using System.Runtime.Remoting.Messaging; private void ActualAsyncMethodCalled() { } private void AsyncMethodCallBack(IAsyncResult result)         {             lock (result)             {                 AsyncResult asyncResult = (AsyncResult) result;                 if (asyncResult.AsyncDelegate != null)                 {                     Action sourceAction = (Action)asyncResult.AsyncDelegate;                     sourceAction.EndInvoke(result);                 }             }         } public void Main() {         Action asyncAction = ActualAsyncMethodCalled;         asyncAction.BeginInvoke(new AsyncCallback(AsyncMethodCallBack), null); } Using Action<T> if the method to be called takes one parameter, always call end invoke when you call begin invoke. Only in windows forms Control.BeginInvoke, this rule is explicitly not required as per MSDN.

Redirecting Console and Debug Output to a textbox.

            _consoleStreamWriter = new TextBoxStreamWriter(txtConsoleOutput, tabConsole);             _debugStreamWriter = new TextBoxStreamWriter(txtDebugOutput, tabDebugPage);             TextWriterTraceListener writer = new TextWriterTraceListener(_debugStreamWriter);             Debug.Listeners.Add(writer);             Debug.WriteLine("Now redirecting debug output.");             // Redirect the out Console stream             Console.SetOut(_consoleStreamWriter);             Console.WriteLine("Now redirecting console output."); To prevent application crash when writing to the Textbox (which will happen with the default code found elsewhere), do the below: public class TextBoxStreamWriter : TextWriter     {         private StringBuilder messageBuilder = new StringBuilder();         private TextBox _output = null;         private Control _parentControl = null;         private System.Timers.Timer _displayTimer = new System.Timers.Timer();       

Merge the state of two objects in C# using reflection

if (fromObject == null || toObject == null) { return; }             PropertyInfo[] properties = typeof(T).GetProperties();             object value = null;             for (int i = 0; i < properties.Length; i++)             {                 if (!properties[i].CanWrite) { continue; }                 value = null;                 IList list = properties[i].GetValue(fromObject, null) as IList;                 if (list != null)                 {                     //Is a list.                     value = list;                 }                 else                 {                     value = properties[i].GetValue(fromObject, null);                 }                 if (doNotMergeIfValueNull && value == null)                 {                     //do nothing.                 }                 else                 {                     properties[i].SetValue(toObject, value, null);                 }             }

Check if something is listening at a port on a server using C#

IPAddress [] hostIPAddresses = Dns.GetHostAddresses(hostName);             IPAddress selectedIPAddress = null;             if (hostIPAddresses == null || hostIPAddresses.Length == 0) { return ListenerStatus.Unknown; }             for (int i = 0; i < hostIPAddresses.Length; i++)             {                 if (hostIPAddresses[i].AddressFamily == AddressFamily.InterNetwork)                 {                     selectedIPAddress = hostIPAddresses[i];                     break;                 }             }             if (selectedIPAddress == null) { return ListenerStatus.Unknown; }             Socket socketInstance = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);             try             {                 socketInstance.Connect(selectedIPAddress, port);                 if (socketInstance.Connected == true)                 {                     //Port is in use and connection is successful                               retu

Retrieving WCF Configuration from C#

WcfConfigDetails details = new WcfConfigDetails();             details.Populated = false;             Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);             ServiceModelSectionGroup serviceModel = ServiceModelSectionGroup.GetSectionGroup(appConfig);             BindingsSection bindings = serviceModel.Bindings;             ChannelEndpointElement element = (from ChannelEndpointElement p in serviceModel.Client.Endpoints                                               where p.Name == endPointName                                               select p).FirstOrDefault();             if (element == null) { return details; }             details.Port = element.Address.Port;             details.HostName = element.Address.Host.ToString();             details.Populated = true;             return details;

Compression & Decompression in C#

Many people search for this. Note I have XML serialized the object because if you do binary serialization, if there are breaking changes in the class, then it will not de-serialize. To compress, do this: CompressionOutput output = new CompressionOutput();             byte[] xmlBytes = Encoding.UTF8.GetBytes(largeString);             MemoryStream memoryStream = new MemoryStream();             try             {                 using (GZipStream zipStream = new GZipStream(memoryStream, CompressionMode.Compress))                 {                     try                     {                         zipStream.Write(xmlBytes, 0, xmlBytes.Length);                     }                     finally                     {                         zipStream.Flush();                         zipStream.Close();                     }                 }                 byte[] compressedData = memoryStream.ToArray();                               if (compressedData.Length < x

How to link Google Analytics to your RSS feed so that you can track how many people visited the feed in ASP.NET

I spent a few days puzzling over this without luck then it hit me! Just create a dummy page which has the Google Analytics JS embedded in it, in the OnInit of your RSS feed, use the System.Net.WebClient to load the dummy ASPX page dynamically: protected override void OnInit(EventArgs e)     {         base.OnInit(e);         try         {             using (WebClient objWebClient = new WebClient())             {                 objWebClient.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");                 Stream data = objWebClient.OpenRead(BASE_URL + "DummyPage.aspx");             }         }         catch { }     }

Distributed Transactions

I recently had a chat with a friend who thought that if we do ADO.NET transactions, those would be distributed transactions. That is obviously incorrect, so I thought let me clarify for everyone here. A Distributed transaction is a transaction which involves multiple resource managers. These could be MSMQ and SQL Server or 2 SQL Server Instances, or SQL Server and Oracle.. etc. Each of these resource managers support transactions within themselves, using that does not mean you are creating a Distributed Transaction, which is actually much more expensive, but necessary in some scenarios where you need transactional integrity. To implement this using .NET, you have to register the assembly with COM+ and use some attributes. It is very interesting and Juval Lowy had written an interesting book on this subject quite some time ago, which also discusses Queued Components interestingly...