top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Using Message Queing In .NET Applications

0 votes
196 views

Introduction

Message Queing provides asynchronous programming model for your applications. For distributed and internet applications whene immediate response is not required from the actual server message quing can be used. This makes your application robust as message delivary is guranteed even if the remote server is out of service.

Namespaces involved

The message quing functionality is available from classes found in System.Messaging namespace. You have to import it in your application.

Imports System.Messaging

Setting up message queues

Before working with message queues you must first create and configure them on your machine. The detailed explanation of creating and configuring is out of scope of this article. I will assume that you have a private queue called MyQueue configured on your machine.

Sending data to message queue

Following code illustrates how to send an entire file to a message queue :

Dim objMsgQ As New MessageQueue
("WIN2000\private$\MyQueue")
Dim newMessage As New System.Messaging.Message()
Dim fs As Stream
fs = File.Open("somepath", FileMode.Open)
newMessage.BodyStream = fs
objMsgQ.Send(newMessage)
fs.Close()
  • We have created instance of MessageQueue and Message classes. The MessageQueue class represents our private queue MyQueue. The Message class represents the actual message i.e. the data that is to be sent over the queue.
  • We then open a local disk file and the file stream is assigned as input to the message BodyStream. In case of simple data like strings you can use other overloaded forms of the Send method.
  • We then sent the data using the Send method of the message queue.

Receiving data from message queue

Now, let us see how to read back the above file once sent into the queue :

Dim mq As MessageQueue = New MessageQueue
("WIN2000\private$\MyQueue")
Dim m As System.Messaging.Message
Dim fs As FileStream
Dim en As New ASCIIEncoding()
Dim data As Integer
Dim s As Stream

m = mq.Receive(New TimeSpan(0, 0, 3))
s = m.BodyStream
fs = File.Create("somepath")
While True
	data = s.ReadByte()
	If data = -1 Then
		Exit While
	End If
	fs.WriteByte(data)
End While
s.Close()
fs.Close()
  • As usual we have created variables of type MessageQueue and Message.
  • We then call Receive method of message queue that actually fetches a message from the queue. We have also specified timeout value for the receive method.
  • We then read BodyStream of the received message and write it to another local file.
posted Dec 7, 2016 by Shivaranjini

  Promote This Article
Facebook Share Button Twitter Share Button LinkedIn Share Button


Related Articles

Introduction

In some cases you need to execute some external application from your own application. The common candidates for such task are:

  • Running BCP in SQL Server
  • Running batch scripts that automate some tasks
  • Start some add-in application like text editor
  • Opening read me kind of files at the end of installation

.NET provides an easy way to execute a process external to your application. In this small article we will see how to do that.

 

Example 1

In this example we will create a console application and see the most basic way of starting an external application.

namespace ConsoleApplicationCS
{
class Class1
{
	static void Main(string[] args)
	{
	System.Diagnostics.Process.Start("notepad.exe");
	}
}
}

The static method - Start of System.Dignostic.Process does the work of starting notepad. Note that since notepad.exe is found on path environment variable we need not give its complete path. For other applications you will have to give full path of the application.

Note : System.Diagnostics also provides classes that allow you read and write to event logs, and monitor system performance using performance counters.

Example 2

In this example we will see how to pass command line arguments to the application

namespace ConsoleApplicationCS
{
class Class1
{
static void Main(string[] args)
{
System.Diagnostics.Process.Start("notepad.exe","sample.txt");
}
}
}

Here, we passed command line arguments for the external application (notepad.exe in our case) via the second argument of the Start method

Example 3

In previous examples you must have noticed that your applications goes on once the process is started. It will not wait for the process to finish. Suppose that you are running SQL Server BCP via Start method and want to process the uploaded data later in your application then your code should not be executed till BCP is finished. In this example we will see how to wait for the process to finish its execution

namespace ConsoleApplicationCS
{
class Class1
{
static void Main(string[] args)
{
System.Diagnostics.Process p=
System.Diagnostics.Process.Start("notepad.exe","sample.txt");
p.WaitForExit();
}
}
}

Actually the Start method returns a reference to the process it starts. The reference is nothing but an instance of Process class. The WaitForExit() method of the instance will 'hold' our application from going further. You can also specify milliseconds to wait for the process if needed.

Example 4

In addition to above, we might need to set parameters like working directory and window style. The ProcessInfo class allows you to do just that. Following code shows its usage:

namespace ConsoleApplicationCS
{
class Class1
{
static void Main(string[] args)
{
System.Diagnostics.ProcessStartInfo psi=
new System.Diagnostics.ProcessStartInfo();
psi.FileName="notepad.exe";
psi.Arguments="sample.txt";
psi.WorkingDirectory="c:\\mywork";
psi.WindowStyle=System.Diagnostics.
ProcessWindowStyle.Maximized;
System.Diagnostics.Process p=
System.Diagnostics.Process.Start(psi);
}
}
}

Here, we set the initial folder or working directory for the application. We also set the window style so that the application will start in maximized window. If you want to hide the process window from the user (very useful for running batch scripts) you can set the window style to hidden.

Some Common Uses

Here are some illustrations of how you can put your knowledge at work:

  • Navigating to a web URL : The Start() method we just saw also accepts file paths or URLs. In such cases a process is started for the application to which the requested document type is associated. For example to open IE and navigate to http://www.microsoft.com you will write some thing like this
    Process.Start("http://www.microsoft.com");
    
  • Open default Email application : You can use same technique to open your default email application.
    Process.Start("mailto:somebody@somedomain.com");
    

Killing a Process

In some rare cases you may need to kill the process you started. You can use Kill() method of the process instance as shown below:

System.Diagnostics.Process p=
System.Diagnostics.Process.Start("notepad.exe","sample.txt");
//some other code
p.Kill();
READ MORE

Introduction

Let's accept the real world fact that you need to write applications targeting not only SQL Server but also many other databases including MS-Access, Oracle and other ODBC databases. Classic ADO was a generic object model. You used to use the same Connection class with SQL Server, Access and Oracle. In ADO.NET, however, you need to use different classes depending on the provider you are using. That means before starting the coding phase you need to be aware of target database. If you develop an application using SQL Server data provider and later on decide to use Oracle you must change your code. At first thought using OLEDB data provider or ODBC data provider might come into your mind. However, considering the performance penalty that is not always a good idea. Won't it be nice to have a generic data access layer which will allow you to write provider independent code? That's exactly what this article will talk about.

Writing generic code with .NET 1.x

In .NET framework 1.x, people wrote generic data access code using interface based approach. You might be aware that all the data provider classes implement certain common interfaces. You can download one such implementation here. You can use the same approach in ADO.NET 2.0 also. However, ADO.NET 2.0 simplifies the job for you. Microsoft has opted for inheritance based approach rather than interface based one. This means all the data provider classes inherit from certain common base classes. For the sake of backward compatibility they still implement the interfaces as before. The following table lists these generic classes:

Data provider classBase class
ConnectionDbConnection
CommandDbCommand
ParameterDbParameter
DataReaderDbDataReader
DataadapterDbDataAdapter
TransactionDbTransaction

 That means SqlConnection and OracleConnection classes inherit from a common base class called DbConnection.

Taking advantage of polymorphism via inheritance we can now write generic code capable of dealing with multiple database in neutral manner. You may feel - "previously there were interfaces now there are common base classes. How does that make your life easy?". But wait. ADO.NET 2.0 has more to offer. In addition to the classes mentioned in the above table, ADO.NET 2.0 also provides a set of classes called "Factory" classes. These factory classes help you to create instances of these base classes dynamically. This ability makes it possible to store the choice of your data provider in a configuration file and then at run time create instances of corresponding data provider classes. For example, SQL server dta provider has a factory class called SqlClientFactory that allows you to create instances of SqlConnection, SqlCommand and so on. Similar classes exists for other data providers also. The SqlClientFactory class has various methods as listed in the following table:

Factory class methodPurpose
CreateConnectionCreates an instance of SqlConnection class
CreateCommandCreates an instance of SqlCommand class
CreateParameterCreates an instance of SqlParameter class
CreateDataAdapterCreates an instance of SqlDataAdapter class
CreateCommandBuilderCreates an instance of SqlCommandBuilder class

Example of writing generic data access code

Let's see with a code snippet how the above classes can be used.

public void ExecuteQuery(string sql,string provider)
{
	DbConnection cnn=null;
	DbCommand cmd=null;
	DbProviderFactory factory = null;
	switch(provider)
	{
	   case "sqlclient":
		   factory = SqlClientFactory.Instance;
		   break;
	   case "oracleclient":
		   factory = OracleClientFactory.Instance;
		   break;
	}
	cnn = factory.CreateConnection();
	cmd = factory.CreateCommand();

	//now use cnn and cmd as usual to execute a query
}

Note, how we used Instance property of SqlClientFactory and OracleClientFactory classes to get an instace of corresponding factory class.

BinaryIntellect DatabaseHelper Open Source Component

BinaryIntellect DatabaseHelper is an open source component that utilizes above features of ADO.NET 2.0 to give you a generic data access layer. You can download the complete source code in C# and VB.NET athttp://www.binaryintellect.com/products/. The download includes a set of samples along with documentation. Here are some core features of the component:

  • Source code available in C# as well as VB.NET
  • Generic data access for all the four data providers of .NET
  • Developed using new Factory classes of ADO.NET 2.0
  • Very small amount of code needed from your side
  • Flexible and easy in use
  • Support for parameterized queries and stored procedures
  • Support for error handling
  • Support for error logging
  • Support for transactions
  • Samples included

Comparing BinaryIntellect DatabaseHelper with MSDAAB

It is possible that you are already using Microsoft Data Access Application Block as a data access layer and might be wondering how BinaryIntellect DatabaseHelper differs from MSDAAB. Though we will not discuss which one is better than the other we will see some main differences between the two.

Difference 1: Target database

MSDAAB is exclusively fro SQL Server databases. However, using BinaryIntellect DatabaseHelper you can write code for all the four data providers of .NET 2.0.

Difference 2: Overall Class Design

MSDAAB extensively uses static methods. There are around 9 overloads per method. As against that BinaryIntellect DatabaseHelper needs to be instantiated and there are four overloads per method.

Difference 3: Working with parameters

using MSDAAB you typically write code as shown below:

SqlParameter[] p=new SqlParameter[2];
p[0]=new SqlParameter("@fname","Bipin");
p[1]=new SqlParameter("@lname","Joshi");
SqlHelper.ExecuteNonQuery("your query here",p);

The problem with this code is that you have provider specific classes such as SqlParameter embedded in your calling code. Even if you decide to use interface based approach you will have parameter specific code in the caller. Let's see the equivalent code in BinaryIntellect DatabaseHelper:

DatabaseHelper db = new DatabaseHelper();
db.AddParameter("@fname", "Bipin");
db.AddParameter("@lname", "Joshi");
object obj=db.ExecuteScalar("your query here");

If you notice the above code it doesn't use any data provider classes in the caller. This means your calling code (such as business logic layer) is database independent.

Difference 4: Executing multiple queries

Many times you need to fire multiple queries at one go. For better performance you would like to held the connection open, fire required queries and then close the connection. MSDAAB allows you to do that but you need to supply the SqlConnection instance from the calling code. This again means that you have data provider classes in the business logic layer. As against this BinaryIntellect DatabaseHelper provides a simple approach. have at look at the following code:

DatabaseHelper db = new DatabaseHelper();
object o = db.ExecuteNonQuery
("query here",ConnectionState.KeepOpen);
object o = db.ExecuteNonQuery("query here");

You do not need to create any connection object in your code. Simply indicate whether you would like to keep the connection open via ConnectionState enumeration. If you do not specify this option the underlying connection is closed.

Difference 5: Working with transactions

MSDAAB expects you to supply the transaction object from your code. This again gives rise to the problem mentioned above. On the other hand BinaryIntellect DatabaseHelper allows much easier way to execute queries under a transaction.

DatabaseHelper db = new DatabaseHelper();
db.BeginTransaction();
int i = db.ExecuteNonQuery
("first query",ConnectionState.KeepOpen);
int j = db.ExecuteNonQuery
("second query", ConnectionState.KeepOpen);
db.CommitTransaction();

Simple. Isn't it?

Difference 6: Error handling

MSDAAB does not provide any error handling facility as such. BinaryIntellect DatabaseHelper on the other hand allows you to handle errors in the component itself. This can simplify your code.

DatabaseHelper db = new DatabaseHelper();
db.HandleErrors = true;
object obj = db.ExecuteScalar("query here");
Console.WriteLine(db.LastError);

Two properties - HandleErrors and LastError does the job for you.

Difference 7: Error logging

MSDAAB does not provide any facility to log database errors (which is a common requirement in many projects). BinaryIntellect allows you to log errors to a text file at a specified location.

DatabaseHelper db = new DatabaseHelper();
db.LogErrors = true;
db.LogFile=@"D:\Bipin\Errorlog.txt";
object obj = db.ExecuteScalar("query here");

Difference 8: Performance

Since MSDAAB uses classes specific to SQL Server, it will give you better performance as compared to generic classes used in BinaryIntellect DatabaseHelper. However, many times the performance difference will be very small.

Summary

ADO.NET 2.0 simplifies writing generic data access code with the help of common base classes and factory classes. If the application requirement calls for provider independence then these classes can significantly help you generalize your code.

READ MORE
...