If you are looking for an introduction to using the System.Data.SqlClient.SqlTransaction class there is a good introduction here.
Remoting is a .net native method of communicating between application domains. Remoting is typically used under the following circumstances:
- Both endpoints are native .net.
- Both endpoints are inside an organisation, as opposed to an internet applicaition.
If the application is internet based and the client platfforms are either unknown or known to be something other that .net then SOAP based web services are typically a better choice. For additional information on how to choose between Web Services and Remoting, start here.
Remoting essentially building a class that can be Marshalled either by reference or by value. Marshalling by reference (the most common form of marshalling used with remoting), establishes a proxy, transparent or otherwise, on the client which takes all method calls on the remoted component, and then sends them back to the server where they are processed and responds to the client via the proxy. This is a complete over simplificaiton of the process and there is a great article from MSDN magazine that expliains it all here.
In it’s simplest form, remoting requires 3 key pieces: the hosting server, the client and the class being remoted. To make the implementation simpler on the client side, and loosely couple the client and server I will introduce another piece which is the ISimpleMaths interface.
ISimpleMaths
ISimpleMaths is an interface that defines four methods, Add, Subtract, Multiply and Divide in the file ISimpleMaths.cs.
using System;
public interface ISimpleMaths
{
int Add(int x, int y);
int Subtract(int x, int y);
int Multiply(int x, int y);
double Divide(int x, int y);
}This interface is compiled into an assembly (ISimpleMaths.dll), which both the server and client compile against, removing the need for the client to compile directly against the server object.
The server object
The heavy lifting of this sample is implemented on the server in the MathsServer class. The MathsServer class inherits from ISimpleMaths and MarshalByRefObject, other than that, this is a basic class that provides methods to perform the simple maths operations. This class is saved in the MathsServer.cs file and compiled into MathsServer.dll with a reference to ISimpleMaths.dll.
using System;
public class MathsServer: MarshalByRefObject, ISimpleMaths
{
public MathsServer()
{
Console.WriteLine("MathServer Constructed.");
}
public int Add( int x, int y)
{
Console.WriteLine("Adding {0} and {1}.",x,y);
return x+y;
}
public int Subtract( int x, int y)
{
Console.WriteLine("Subtracting {0} from {1}.",x,y);
return x-y;
}
public int Multiply( int x, int y)
{
Console.WriteLine("Multiplying {0} and {1}.",x,y);
return x*y;
}
public double Divide( int x, int y)
{
Console.WriteLine("Dividing {0} by {1}.",x,y);
return (double)x/(double)y;
}
}The Remoting Server
The remoting server itself is very simple, it opens up a TCP channel, instantiates an instance of the MathsServer class and then marshals that instance ready to be invoked by a client. The RemotingServer.cs file is compiled into RemotingServer.exe and links in MathsServer.dll as well as the appropriate remoting dll.
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
class RemotingServer
{
static int Main ()
{
// Use port 1122 for TCP communications.
// In a real applicaiton this would be a config file setting.
int TCP_PORT = 1122;
// Open up the Remoting TCP Channel on
Console.WriteLine("Starting Server");
TcpChannel ch = new TcpChannel(TCP_PORT);
ChannelServices.RegisterChannel (ch);
// Instantiate the MathsServer object
MathsServer Server = new MathsServer();
// Marshall the MathsServer object so it can be used
RemotingServices.Marshal(Server,"maths.rem");
Console.WriteLine("Server Running ...");
Console.WriteLine("Press [Enter] to exit.");
// When someone hits enter shut the server down.
Console.ReadLine();
ch.StopListening (null);
// Retun an exit code of 0 as per convention.
return 0;
}
}The Client
The final piece of the sample is the client.
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
class RemotingClient
{
public static int Main()
{
TcpChannel ch = new TcpChannel(0);
ChannelServices.RegisterChannel (ch);
object RemoteObject = Activator.GetObject(typeof(ISimpleMaths),
"tcp://localhost:1122/maths.rem");
ISimpleMaths MathsSrv = (ISimpleMaths)RemoteObject;
//Add something
int bob = MathsSrv.Add(1,2);
Console.WriteLine("Adding 1 and 2 result is :{0}",bob);
// Subtract something
bob = MathsSrv.Subtract(2,1);
Console.WriteLine("Subtract 1 from 2 result is :{0}",bob);
//Add something
bob = MathsSrv.Multiply(1,2);
Console.WriteLine("Multiplying 1 and 2 result is :{0}",bob);
// Divide something
double tom = MathsSrv.Divide(4,2);
Console.WriteLine("Dividing 4 and 2 result is :{0}",tom);
//Return 0 as per convention
return 0;
}
}Building the Sample
This sample can be easily built on any machine with either Mono 1.01 or any version of the .Net SDK installed.
On a machine with mono, build the sample as follows:
mcs /t:library ISimpleMaths.cs mcs /t:library /r:ISimpleMaths.dll MathsServer.cs mcs /r:MathsServer.dll /r:System.Runtime.Remoting.dll RemotingServer.cs mcs /r:ISimpleMaths.dll /r:System.Runtime.Remoting.dll MathsClient.cs
On windows, you will need to use the .net Command prompt to build like this:
csc /t:library ISimpleMaths.cs csc /t:library /r:ISimpleMaths.dll MathsServer.cs csc /r:MathsServer.dll /r:ISimpleMaths.dll RemotingServer.cs csc /r:ISimpleMaths.dll MathsClient.cs
If it all works as planned
Hopefully everything should have compiled OK and you can open up two terminal windows.. In the first start there server RemotingServer.exe and you should see the following output.
Starting Server MathServer Constructed. Server Running ... Press [Enter] to exit.
The client window should see it’s work being very generiously being performed by a server. There should be some output as follows.
Adding 1 and 2 result is :3 Subtract 1 from 2 result is :1 Multiplying 1 and 2 result is :2 Dividing 4 and 2 result is :2
So there you have it, a simple working example of .net remoting, Interestingly whilst writing this article I pointed my windows machine at my Powerbook and got the following division result.
Dividing 4 and 2 result is :3.16202013338398E-322
This shows that it always pays to check your results are what they should be. Without investigating this I would guess that this appears to be a endianness problem.
Additional Information
I ran into a couple of simple gotcha’s when I tried to install Northwind on SQL Express Beta 2, so I thought that there would be some value in documenting the steps that are required.
Step 1 – Download and install SQL Server Express, at the time of writing you can get Beta 2 from here.
Step 2 – Download and install the Northwind database installer scripts from here.
Step 3 – The Northwind installer copies the setup scripts to the “c:\Program Files\Microsoft SQL Server 2000 Sample Database scripts” directory. Change into that directory.
When SQL Express Beta 2 it installs into an instance called SqlExpress. This is the main gotcha that seems to be catching out most people, who are used to having SQL Server only installed on the default instance. To refer to this instance you need to add a “.\” as a prefix to the instance name, or .\SqlExpress.
Step 4 – Install the Northwind sample database with the following command line: osql -E -S .\SqlExpress -i instnwnd.sql, and that should do it. be sure to note the .\ in front of SqlExpress. Also please try and not confuse .\ with this website.
I have been tinkering with Mono on my PowerBook since the 1.0.1 release, and whilst I wouldn’t consider running any production software on it, it is great to be able to develop in C# and run simple ASP.NET pages on Mac OS X.
That said, despite the installer packages that are available, it definitely falls victim to the same problems as the majority of all open source projects; you need a lot of patience and smarts to get things working.
Take ASP.NET as an example. To get mod_mono working on my machine, I had to get the latest sources from CVS, the day after the 1.0.1 release was made. Whilst this is not a huge issue in itself, if this was a commercial product, the company releasing it would be lynched. Why, let me explain.
mod_mono and XSP not working on Mac OS X was a Severity 1 bug, with part of the intial mono release but they shipped it anyway. A Severity 1 bug is typically defined as a “Major crash or data loss with no workaround.” In the land of commercial software development, you simply do not ship with this type of bug present, because there is no point. The last thing that you customers want to hear is: “Dear Mr Customer, here is our product, sorry though it doesn’t work because of a Sev 1 bug.”
But Mono is open source, and no money changes hands, so we can let this slip and wait for the next release, and I’ll try and sort it myself. The next problem was that the bug was marked resolved in the bug tracking system, and yet (at the time of writing), the fix is still not yet released. There are no notes in the defect saying which version it was fixed in, and it required a: “Grab the latest release from CVS and see what happens” approach at solving the problem.
I don’t want to use this post as an attack on Mono, it is bloody brilliant what these guys have done. I just wanted to give an example of how open source projects could lift their game and follow the same conventions used in the commercial software world. And that is: if it’s broken it ain’t done, no matter how important your ship date is.
It’s always good to see a company practising what it preaches, and Microsoft have just performed what must be one of the most visible executions of trade-off through the decision to ship Longhorn without WinFS and optimise for schedule.
For a product like an operating system, it seems logical that there would be two key “phases” where trade-off would be lead by distinctly different priorities. Initially in the development cycle, the balance would be geared towards features over schedule, to help flush out the cool new features that will provide a compelling reason for customers to upgrade to the new version.
Once the compelling features have been designed and initially developed then the project should switch into ship mode and change the priority to hitting a schedule, otherwise there is a danger of becoming like Taligent and never shipping anything. (Don Box uses a term called: “The Taligent Effect”, which he discusses here.)
