top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Cryptography And .NET Framework - Part 2 (Secret Key Encryption)

0 votes
501 views

Introduction

In the Part 1 we learnt the basics of Cryptography and related .NET Framework classes. In this article we are going to see how to work with Secret Key Encryption using Triple-DES algorithm.

Triple-DES

The System.Security.Cryptography namespace contains a class called TripleDESCryptoServiceProvider that provides Triple-DES encryption to your data. DES stands for Data Encryption Standard and the word triple is used because it encrypts the original data thrice.

The secret key encryption needs two things to encrypt the data:

  • A secret key
  • An initialization vector

The encryption algorithms employ use a chaining technique to encrypt the data. In this technique the entire data to be encrypted is divided in smaller blocks. The previously encrypted block of data is used to encrypt the current one and the process repeats.

The Initialization Vector (IV) serves as a seed that is used to encrypt and decrypt the first block of bytes. This ensures that no two blocks of data produce the same block of encrypted text.

For using TripleDESCryptoServiceProvider the encryption key must be of 24 bytes and the initialization vector must be of 8 bytes.

Example of using TripleDESCryptoServiceProvider class

In this example we will first create a class called SecurityHelper that will help us encrypt and decrypt string data. Here is the code for the class:

Imports System.Security.Cryptography
Imports System.IO
Imports System.Text
Public Class SecurityHelper
    Public Key() As Byte
    Public IV() As Byte
    Public Function Encrypt(ByVal strData As String) As Byte()
        Dim data() As Byte = ASCIIEncoding.ASCII.GetBytes(strData)
        Dim tdes As TripleDESCryptoServiceProvider = 
	New TripleDESCryptoServiceProvider
	If Key Is Nothing Then
		tdes.GenerateKey()
		tdes.GenerateIV()
		Key = tdes.Key
		IV = tdes.IV
	Else
		tdes.Key = Key
		tdes.IV = IV
	End If
        Dim encryptor As ICryptoTransform = 
	tdes.CreateEncryptor()
        Dim ms As New MemoryStream
        Dim cs As CryptoStream = 
	New CryptoStream(ms, encryptor, CryptoStreamMode.Write)
        cs.Write(data, 0, data.Length)
        cs.FlushFinalBlock()
        ms.Position = 0
        Dim result(ms.Length - 1) As Byte
        ms.Read(result, 0, ms.Length)
        cs.Close()
        Return result
    End Function
    Public Function Decrypt(ByVal data() As Byte) As String
        Dim tdes As TripleDESCryptoServiceProvider = 
	New TripleDESCryptoServiceProvider
        tdes.Key = Key
        tdes.IV = IV
        Dim decryptor As ICryptoTransform = 
	tdes.CreateDecryptor()
        Dim ms As New MemoryStream
        Dim cs As CryptoStream = 
	New CryptoStream(ms, decryptor, CryptoStreamMode.Write)
        cs.Write(data, 0, data.Length)
        cs.FlushFinalBlock()
        ms.Position = 0
        Dim result(ms.Length - 1) As Byte
        ms.Read(result, 0, ms.Length)
        cs.Close()
        Return ASCIIEncoding.ASCII.GetString(result)
    End Function
End Class

Let's examine the code step by step:

  • We create a class called SecurityHelper with two functions Encrypt() and Decrypt(). The former accepts the string to be encrypted and returns encrypted form of the string as a byte array. The later accepts the encrypted data in the form of a byte array and returns decrypted data as a string.
  • The class has two public variables of byte array type. They are used to assign the secret key and initialization vector.
  • In the Encrypt() function we first convert the string to be encrypted into a byte array using GetBytes() method.
  • We then create an instance of TripleDESCryptoServiceProvider class
  • The key and initialization vector can be supplied externally by you or TripleDESCryptoServiceProvider class can generate one automatically for you. If user has not supplied key and IV we call GenerateKey() and GenerateIV() methods respectively. These methods create a random key and IV automatically for you. We assign the generated key and IV to public variables Key and IV.
  • Then we call CreateEncryptor() method of TripleDESCryptoServiceProvider class and collect its return value in a variable of type ICryptoTransform. The ICryptoTransform interface defines the basic operations of cryptographic transformations.
  • We then create a memory stream. The encrypted data will be put inside this stream.
  • We also create a CryptoStream and pass the memory stream and the encryptor created above.
  • Next, we write the data to be encrypted to the CryptoStream object. The CryptoStream object stores the encrypted version of the data in the supplied memory stream.
  • Finally, we read the memory stream for encrypted data. Put that data in an array of bytes and return it to the caller.

Decryption process is similar but follows reverse path. The only major difference between encryption and decryption code is that in case of decryption we call CreateDecryptor() method of TripleDESCryptoServiceProvider class.

Summary

In this article we saw how TripleDESCryptoServiceProvider class can be used to encrypt and decrypt string data. With little or no modification you can reuse the class for your own requirements. Some common uses of this algorithm can be - storing passwords in database, string confidential data such as bank account numbers etc. in database. In the example above we used memory stream to put our data but you can also use FileStream to save the data to a disk file. In the next article we will see how to use public-key encryption.

posted Dec 9, 2016 by Shivaranjini

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


Related Articles

Introduction

In the Part 2 of this series we learnt to use Secret Key Encryption techniques using Triple-DES algorithm. More often to transfer data encrypted via secret key encryption public key encryption is used. This puts one extra layer of security over the data being transferred. From Part 1 we know that public key encryption consists of two keys - public key and private key. Data encrypted by public key can be decrypted only by the corresponding private key and vice a versa. One of the most popular algorithm for encrypting and decrypting data using this technique is RSA. The acronym RSA stands for Rivest, Shamir, and Adelman who are the inventors of the technique. The .NET framework provides a class called RSACryptoServiceProvider that encapsulates this algorithm. In this article we are going to learn how to use this class to secure your data.

Developing a class for encryption and decryption

Many developers don't want to go into the internals of Cryptography. They simply need a quick and easy way to secure their data. So we are going to develop such reusable class that will do the job of encrypting and decrypting for us.

We will create a class called PublicKeySecurityHelper which will have two methods - Encrypt and Decrypt. In addition we will also create a helper class called MyRSAInfo. This class will simply store certain pieces of data (such as public key and private key).

Here, is the complete code of the class.

Imports System.Security.Cryptography
Imports System.IO
Imports System.Text

Public Class PublicKeySecurityHelper
    Public Function Encrypt(ByVal strData As String) As MyRSAInfo
        Dim myrsa As New MyRSAInfo
        Dim p As CspParameters = New CspParameters
        p.Flags = CspProviderFlags.UseMachineKeyStore
        myrsa.Parameters = p
        Dim rsa As RSACryptoServiceProvider = 
	New RSACryptoServiceProvider(p)
        Dim data() As Byte = 
	rsa.Encrypt(Encoding.Unicode.GetBytes(strData), False)
        myrsa.PublicKey = rsa.ToXmlString(False)
        myrsa.PrivateKey = rsa.ToXmlString(True)
        myrsa.Data = data
        Return myrsa
    End Function
    Public Function Decrypt(ByVal myrsa As MyRSAInfo) As Byte()
        Dim rsa As RSACryptoServiceProvider = 
	New RSACryptoServiceProvider(myrsa.Parameters)
        rsa.FromXmlString(myrsa.PublicKey)
        Dim data() As Byte = rsa.Decrypt(myrsa.Data, False)
        Return data
    End Function
End Class
Public Class MyRSAInfo
    Public PublicKey As String
    Public PrivateKey As String
    Public Parameters As CspParameters
    Public Data() As Byte
End Class

Let's dissect the code step by step:

Encrypting data

  • First we import the required namespaces. Especially System.Security.Cryptography is important one because it contains our core class RSACryptoServiceProvider
  • We create a method called Encrypt() that accepts the string to be encrypted and returns an instance of a class called MyRSAInfo
  • MyRSAInfo is our custom class defined at the bottom of the code. It consists of four public members - PublicKey, PrivateKey, Parameters and Data
  • The PublicKey and PrivateKey members store the generated public key and private key respectively.
  • The Parameters variable is of type CspParameters. This is used to automatically generate public and private keys and reuse them later on.
  • The Data is an array of bytes and stores the encrypted version of the data
  • Inside the Encrypt() method we create an instance of CspParameters class and set its Flag property to CspProviderFlags.UseMachineKeyStore. This enumerated value specifies from where the key information should be picked up i.e. from default key container or from machine level key store.
  • Then we create new instance of RSACryptoServiceProvider class passing the CspParameters instance.
  • We then call Encrypt() method of RSACryptoServiceProvider class and pass data to be encrypted. Since this parameter is byte array we convert our string into byte array using GetBytes() method. The second parameter of the method indicates whether to use OAEP padding (true) or PKCS#1 v1.5 padding (false). The former can be used only on Windows XP machines and hence we pass False. The Encrypt() method of RSACryptoServiceProvider class returns a byte array that contains encrypted version of the data.
  • Finally, we fill all the members of MyRSAInfo class and return to the caller. Note how we call ToXmlString() method first passing False and then passing True to get public and private keys respectively.

Decrypting data

  • In order to decrypt the data we create a method called Decrypt() that accepts an instance of MyRSAInfo class. This instance must be the one returned by the Encrypt() method explained earlier.
  • Inside Decrypt() method we create an instance of RSACryptoServiceProvider class again passing the same CspParameters.
  • We then call FromXmlString() method of the RSACryptoServiceProvider class and pass the public key generated before.
  • Finally, we call Decrypt() method of RSACryptoServiceProvider class and pass the encrypted data. The second parameter of Decrypt method has the same significance as that of the corresponding parameter of Encrypt() method

Download

Complete source code along with a sample usage is available for download with this article (see top).

Summary

Public key encryption is a secure way to transfer data over networks. The fact that the private key is not sent in unsafe manner makes it more secure and robust. This technique is used in Secure Socket Layer (SSL) or HTTPS based web sites. The .NET framework class RSACryptoServiceProvider allows you to generate public and private keys, encrypt and decrypt data. In the next article we will learn about digital signatures. Stay tuned!

READ MORE

Introduction

Security is key consideration for many applications. Providing authentication and authorization services to your application is just one part of the overall security. What about the data that is being used and transferred in the application? That is where cryptography comes into picture. Cryptography is a huge topic by itself. In this series of articles I am going to confined our discussion only to .NET Framework and cryptographic classes provided by it.

Why use Cryptography?

Many times application provide security features such as login forms and role based security. However, what if someone intercepts the data that is being flown over the network? What if someone plays with the data that is being transmitted over the network? What if someone opens SQL Server database that is storing passwords? Cryptography provides solution to such questions. Using .NET Cryptographic classes you can encrypt the data that is being flown in your system or network and then decrypt when you want authenticated user to modify or read it. In short Cryptography provides following features:

  • Protect data being transferred from reading by third parties
  • Protect data being transferred from any modification
  • Make sure that data is arriving from the intended location

Types of Cryptographic classes

The overall Cryptographic classes available in .NET framework can be classified in four categories:

  • Classes that deal with secret key encryption (also called as Symmetric Cryptography)
  • Classes that deal with public key encryption (also called Asymmetric Cryptography )
  • Classes that deal with digital signatures (also called cryptographic signatures)
  • Classes that deal with cryptographic hashes

All the cryptography related classes can be found in System.Security.Cryptography namespace.

Secret Key Encryption

In Secret Key Cryptography the data being protected is encrypted using a single secret key. This key is known only to sender and receiver. The sender encrypts the data using the secret key. The receiver decrypts the data using the same secret key. It is very important to keep the key secret otherwise anybody having the key can decrypt the data.

.NET Framework provides following classes to work with Secret Key Cryptography:

  • DESCryptoServiceProvider
  • RC2CryptoServiceProvider
  • RijndaelManaged
  • TripleDESCryptoServiceProvider

Public Key Encryption

Unlike secret key encryption, public key encryption uses two keys. One is called public key and the other is called as private key. The public key is not kept secret at all where as private key is kept confidential by the owner of that key. The data encrypted by private key can be decrypted only using its corresponding public key and data encrypted using public key can be decrypted using its private key. Naturally, in order to encrypt the data being transmitted you need to use public key. This data can be decrypted only with the corresponding private key.

.NET Framework provides following classes to work with public key encryption:

  • DSACryptoServiceProvider
  • RSACryptoServiceProvider

Digital Signatures

Digital signatures are used to verify identity of the sender and ensure data integrity. They are often used along with public key encryption. Digital signature work as follows:

  1. Sender applies hash algorithm to the data being sent and creates a message digest. Message digest is compact representation of the data being sent.
  2. Sender then encrypts the message digest with the private key to get a digital signature
  3. Sender sends the data over a secure channel
  4. Receiver receives the data and decrypts the digital signature using public key and retrieves the message digest
  5. Receiver applies the same hash algorithm as the sender to the data and creates a new message digest
  6. If sender's digest and receiver's digest match then it means that the message really came from the said sender.

The classes DSACryptoServiceProvider and RSACryptoServiceProvider are used to create digital signatures.

Hashes

Hash algorithms create a fixed length output for a given variable length data. If somebody changes the original data even slightly then the hash generated will be different than original hash. They are often used with digital signatures.

Some of the classes in .NET that deal with hashes are:

  • SHA1Managed
  • MD5CryptoServiceProvider
  • MACTripleDES

Random Number Generators

While working with cryptography classes many times you need to generate cryptographic keys. Random number generators are used for this purpose. .NET provides a class called RNGCryptoServiceProvider to generate such random numbers.

In the next article we will see how the secret key encryption can be done using the relevant classes.

READ MORE

Introduction

In previous parts of this series (Part 1Part 2 and Part 3) we saw various techniques of encrypting the data. In this part we are going to learn how to ensure that data coming to you has not been tampered with during the transfer. The technique that we will be using is hash. Hash values allow us to verify the integrity of data. The hash value of received data can be compared to the hash value of data that was sent to check if the data is tampered.

.NET Framework classes for creating hashes

.NET Framework provides following main classes to work with hashes:

  • SHA1Managed
  • MD5CryptoServiceProvider
  • MACTripleDES

Since SHA1 is now a broken algorithm, we will use MD5CryptoServiceProvider to generate hash values.

Example

We are going to create a helper class that will help us create and verify hash values using MD5 algorithm. The class contains two methods - GetHash() and VerifyHash(). The former accepts string whose hash value is to be generated and returns the computed hash as a byte array. The later accepts the message as it was received and the hash generated previously and returns true if the message is not altered during transmit otherwise returns false.

public class MD5HashHelper
{
public byte[] GetHash(string message)
{
byte[] data;
data=System.Text.UTF8Encoding.ASCII.GetBytes(message);
MD5CryptoServiceProvider md5=new MD5CryptoServiceProvider();
return md5.ComputeHash(data,0,data.Length);
}
public bool VerifyHash(string message, byte[] hash)
{
byte[] data;
data=System.Text.UTF8Encoding.ASCII.GetBytes(message);
MD5CryptoServiceProvider md5=new MD5CryptoServiceProvider();
byte[] hashtemp=md5.ComputeHash(data,0,data.Length);
for(int x = 0; x < hash.Length;x++)
{
if (hash[x] != hashtemp[x])
{
return false;
}
}
return true;
}
}

Let's dissect the code step by step:

  • We first need to import System.Security.Cryptography namespace in your class
  • The GetHash() accepts string whose hash value is to be generated and returns the computed hash as a byte array.
  • Inside the function we used UTF8Encoding class and get aa byte representation of the string to be transfered.
  • We then create an instance of MD5CryptoServiceProvider class and call its ComputeHash by passing the byte created above to it.
  • The ComputeHash() function generates the hash for the given data and returns another byte array that represents the hash value of the data.
  • The VerifyHash() function accepts the message as it was received and the hash generated previously and returns true if the message is not altered during transmit otherwise returns false.
  • Inside this function we again use UTF8Encoding class and generate byte representation of the received message.
  • We then compute hash for this data using the same ComputeHash() method of MD5CryptoServiceProvider class.
  • Finally, we run a for loop and check each and every byte of original hash value and the hash we generated above. If both the hash values are matching we can conclude that the data is not tampered.

Download

Complete source code along with a sample usage is available for download with this article (see top).

Summary

In this example we saw how to ensure data integrity using MD5 hashing algorithm. In the next article on the series we will learn to generate digital signatures.

READ MORE

What's the magic that actually distributes the load, and how does it determine how the distribution is handled?

At ORCS Web we use the Foundry Server Iron products to perform our webfarm load-balancing. If one of them fails, the other instantly takes over (In our testing, it had sub-second fail-over!)

So what is this "Server Iron" thing? In simplest terms, it's a layer 4-7 switch. It has multiple network ports on it and can be used literally like other types of switches. But, it can also load-balancing and traffic distribution. A VIP (virtual IP) can be assigned to the SI (Server Iron) and it then handles all traffic sent to that address/VIP. Further configuration is done to tell the SI what to actually do with the traffic sent to the VIP address.

The traffic that hits the VIP on the Server Iron is of course redistributed to a number of server nodes so the client request can be satisfied - that's the whole point of a webfarm. If one or more server nodes are not responding, the switches are able to detect this and send all new requests to servers that are still online - making the failure of a server node almost transparent to the client.

The traffic can be distributed based on a couple different logic algorithms. The most common are:

 

 

 

 

  • Round Robin: The switches send requests to each server in rotation, regardless of how many connections each server has or how fast it may reply.
  • Fastest response: The switches select the server node with the fastest response time and sends new connection requests to that server.
  • Least connections: The switches send traffic to whichever server node shows as having the fewest active connections.
  • Active-passive: This is called Local/Remote on a Foundry switch, but is still basically active/passive. This allows one or more servers to be designated as "local" which marks them as primary for all traffic. This is combined with another method above to determine what order the "local" server nodes have requests sent to them. If a situation were to arise that all the "local" (active) server nodes were down, then traffic would be sent to the "remote" server nodes. Note that "remote" in this case doesn't really have to mean remote - the "remote" server could be sitting right next to the "local" servers but it is marked as remote in the configuration to let it operate as a hot-standby server. This setting can also be used in a true remote situation where there are servers in a different physical data center - perhaps for extreme disaster recovery situations.

What method is best? It really depends on your application and some other surrounding factors. Each method is good though and would probably satisfy requirements regardless of the configuration. Especially if you are closely monitoring each server node with an external tool (other than directly from the load-balancing switch). So, with the external monitoring you can confirm that all server nodes are operating without error and within reasonable speed thresholds that have been set.

Also, remember that, regardless which traffic algorithm is chosen, if a node goes down, traffic is sent to the other nodes. And when a node comes back online, it can automatically be placed back into the webfarm and start getting client requests again.

Clustered hosting does require some consideration of how state is managed within applications, which will be covered in a future article.

Happy hosting!

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
...