top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Dealing With Optimistic Concurrency In Entity Framework

0 votes
251 views

When you update a database record with the entity values, the database values are overwritten by the entity values (default behavior). In a real world situation it is quite possible that database values might have got changed after selecting them for modification. In such cases, your update operation might be overwriting changes made by someone else. That is why it becomes important to detect if concurrency violation has occurred. You can then take some corrective action or at least inform the user about such a violation. To that end this article shows how to detect concurrency violation in EF and also the possible ways to deal with the situation.

Detecting Concurrency Violation

Entity Framework can be configured to use optimistic concurrency while updating database records. That means no locks are held on the data being modified. The data is updated only if the database values at the time of fetching the data and the database values currently stored in the database match. To understand how the concurrency violation can be detected, let's develop a simple application that updates Employee details from Employees table. The Employees table consists of the columns shown by the following data model:

image

As you can see the Employees table has five columns: EmployeeID, FirstName, LastName, Title and UpdateToken. Most of the columns are self explanatory except UpdateToken. The UpdateToken column is of type rowversion. The rowversion data type ensures that the column holds a different value every time that record is updated. A rowversion column is automatically updated by the SQL Server and it won't play any direct role in your application data. Why do you need a rowversion column here? That's because it allows us to detect if a record has been changed after the initial selection. However, merely adding a rowversion column is not sufficient. In the entity framework designer you also need to set the ConcurrencyMode property of the UpdateToken property to Fixed. The following figure shows how this is done:

image

As you can see the Concurrency Mode is changed from None to Fixed. Changing this setting will cause EF to use the UpdateToken column in the WHERE clause of the UPDATE queries it generates. This way a row is updated only when value of UpdateToken at the time of initial fetch matches with the current value in the database. If they don't match no record is updated and EF concludes that there was a concurrency violation.

You can also detect a concurrency violation without using rowversion column. In that case you need to set ConcurrencyMode for each property that you wish to include in the WHERE clause. Using rowversion column simplifies your job and the resultant query.

Creating a Web Form

The data from the Employees table is shown in a DetailsView as shown below:

image

In order to bind this DetailsView with EF data model you need to write two methods in the code behind - DetailsView1_GetItems() and DetailsView1_UpdateItem(). The former method returns all the Employee objects from the Employees DbSet as IQueryable whereas the later method updates employee details back to the database. Below the DetailsView place a Label (not shown in the figure) to display the concurrency violation error.

The DetailsView1_GetItems() method is given below:

public IQueryable<Employee> DetailsView1_GetItems()
{
  EmployeeDbEntities db=new EmployeeDbEntities();
  var query = from e in db.Employees
              orderby e.EmployeeID
              select e;
  return query;
}

The DetailsView1_GetItems() method creates an instance of EmployeeDbEntities context. It then selects all Employee objects from Employees DbSet and returns them to the caller.

The DetailsView1_UpdateItem() method is shown below:

public void DetailsView1_UpdateItem(int EmployeeID)
{
  EmployeeDbEntities db=new EmployeeDbEntities();
  Employee item = db.Employees.Find(EmployeeID);
  TryUpdateModel(item);
  System.Threading.Thread.Sleep(15000);
  try
  {
    db.SaveChanges();
  }
  catch(DbUpdateConcurrencyException ex)
  {
    lblErr.Text = ex.Message;
  }
}

The above code finds an existing Employee based on the EmployeeID. Remember that this EmployeeID is passed by the DetailsView only if DataKeyNames property is set. The TryUpdateModel() method then sets the properties of the existing Employee from the values entered in the DetailsView. The code then halts the execution for 15 seconds. This is done purely for the sake of testing. Adding this delay will allow you to switch to the physical database table and modify its data manually to test the concurrency violation. An alternative is to set a breakpoint at SaveChanges() method to halt the execution and then change the database values manually.

The try...catch block is an important piece of code because it traps the concurrency violation error and displays it to the user. The try block attempts to save the changes back to the database by calling SaveChanges() method. If there are pending changes but SaveChanges() causes zero records to be updated it indicates a concurrency violation. If such a violation is detected EF throws DbUpdateConcurrencyException exception. The DbUpdateConcurrencyException class resides in System.Data.Entity.Infrastructure namespace. The catch block simply displays the error in the Label control.

To test what you developed so far, run the Web Form and modify an employee record. After clicking the Update button quickly switch to the database in Server Explorer of Visual Studio and modify the same record with some different values (you have 15 seconds to do this change!) and wait to see what is thrown on the screen. The following figure shows a sample run of the Web Form with the error:

image

During the above test run you will find that after the error message is displayed to the user, the DetailsView shows the latest data from the database.

Handling Concurrency Violation

 Once you detect concurrency violation, the next step is to decide what action to take. There are three approaches that you can take:

  • Do nothing. Simply show the error message to the user and exit from the data modification stage.
  • Update the entity under consideration from the latest data from the database table. Then show that data to the user so that he can take the necessary action.
  • Forcefully update the database table with the values from the entity.

The first approach is quite easy and that is what you used in the preceding example. The second approach requires you to load database values in an entity and present them to the user. You can do that in the catch block as shown below:

...
catch(DbUpdateConcurrencyException ex)
{
  lblErr.Text = "Concurrency violation! Please review the latest values shown above.";
  ex.Entries.Single().Reload();
  DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}

As you can see the DbUpdateConcurrencyException class provides access to the entity causing the error. The Reload() method called on an entity loads the values from the database into that entity. You then change the mode of the DetailsView to ReadOnly so that user can read the new values.

In the third approach, you make the current database values as the original values and then attempt SaveChanges() again. This approach is shown below:

...
catch(DbUpdateConcurrencyException ex)
{
  lblErr.Text = "Concurrency violation! Attempting to force save to the database.";
  var emp = ex.Entries.Single();
  emp.OriginalValues.SetValues(emp.GetDatabaseValues());
  db.SaveChanges();
}

Here, you set the OriginalValues of the entity under consideration to the current values from the database (obtained by calling GetDatabaseValues()). You then attempt SaveChanges() again.

You can test the same Web Form by adding the code for second and third approaches discussed above and verify whether it works as expected.

posted Dec 22, 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

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.

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