White Paper On ConCurrency For PCMS Application Architecture

13
Currency Architecture A cross referenced white paper Dated: 19 th July 2009 Version: 1.0 By: Shahzad Sarwar, PSE, Comsoft To: Nafees Yousaf, Manager, Comsoft Related Project Managers/Consultants Development Team

description

White Paper On ConCurrency For PCMS Application Architecture

Transcript of White Paper On ConCurrency For PCMS Application Architecture

Page 1: White Paper On ConCurrency For PCMS Application Architecture

Currency Architecture A cross referenced white paper

Dated: 19th July 2009 Version: 1.0 By: Shahzad Sarwar, PSE, Comsoft

To: Nafees Yousaf, Manager, Comsoft Related Project Managers/Consultants Development Team

Page 2: White Paper On ConCurrency For PCMS Application Architecture

Table of content

1. Revision History...................................................................................................................32. What is Concurrency/Locking?..........................................................................................33. Types of Concurrency.........................................................................................................34. Difference between Pessimistic Concurrency and Optimistic Concurrency..................35. Implementation of Optimistic Concurrency:......................................................................3

5.1. For .Net Data (Adapter)...............................................................................................35.2. For ASP .Net.................................................................................................................55.3. For Nhibernate:............................................................................................................65.4. For LINQ to SQL...........................................................................................................9

5.4.1. Conflict Detection and Resolution Checklist....................................................95.4.2. Types That Support Conflict Discovery and Resolution...............................10

6. Implementation of Pessimistic Concurrency:.................................................................106.1. For .Net....................................................................................................................... 106.2. For ASP .Net...............................................................................................................106.3. For Nhibernate:..........................................................................................................106.4. For LINQ to SQL.........................................................................................................10

7. Reference:........................................................................................................................... 107.1. .Net.............................................................................................................................. 107.2. ASP .Net.....................................................................................................................107.3. LINQ 2 SQL.................................................................................................................107.4. Nhibernate:.................................................................................................................11

Page 3: White Paper On ConCurrency For PCMS Application Architecture

1. Revision HistorySNO Details Author Date version1 Points 2 to 5 and point 7 Shahzad Sarwar 19th July 2009 1.02 Point 6 Shahzad Sarwar Next week 1.13

2. What is Concurrency/Locking?

Locking is a method used to protect records that will be accessed by multiple users so that concurrency errors do not occur (when multiple users change records near simultaneously resulting in inconsistencies)."Locking" refers to preventing access in some way to the file in order to protect it while a user is making an update.

3. Types of Concurrency

There are 2 types of locking / Concurrency • Pessimistic Concurrency• Optimistic Concurrency

4. Difference between Pessimistic Concurrency and Optimistic Concurrency

In Pessimistic concurrency the server acquires locks to block access to data that another process is using. Pessimistic concurrency avoids conflicts by acquiring locks on data that is being read, so no other process can modify that data, it also acquires locks on data being modified so no other processes can access that data for either reading or modifying. Readers block writers and writers block readers.

In Optimistic Concurrency the server uses row versioning to allow data readers to see the state of the data before the modifications occur. Older versions of data rows are saved so a process reading data can see the data as it was when the process started reading and not be affected by any changes being made to that data. A process that modifies data is unaffected by processes reading the data because the readier is accessing a saved version of the data rows, readers do not block writers and writers do not block readers.

5. Implementation of Optimistic Concurrency:

5.1. For .Net Data (Adapter)

The following is a simple example that sets the UpdateCommand of a DataAdapter to test for optimistic concurrency, and then uses the RowUpdated event to test for optimistic concurrency violations. When an optimistic concurrency violation is encountered, the application sets the RowError of the row that the update was issued for to reflect an optimistic concurrency violation.Note that the parameter values passed to the WHERE clause of the UPDATE command are mapped to the Original values of their respective columns.[C#] SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");

Page 4: White Paper On ConCurrency For PCMS Application Architecture

SqlDataAdapter custDA = new SqlDataAdapter("SELECT CustomerID, CompanyName FROM Customers ORDER BY CustomerID", nwindConn);

// The Update command checks for optimistic concurrency violations in the WHERE clause. custDA.UpdateCommand = new SqlCommand("UPDATE Customers (CustomerID, CompanyName) VALUES(@CustomerID, @CompanyName) " + "WHERE CustomerID = @oldCustomerID AND CompanyName = @oldCompanyName", nwindConn); custDA.UpdateCommand.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); custDA.UpdateCommand.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 30, "CompanyName");

// Pass the original values to the WHERE clause parameters. SqlParameter myParm; myParm = custDA.UpdateCommand.Parameters.Add("@oldCustomerID", SqlDbType.NChar, 5, "CustomerID"); myParm.SourceVersion = DataRowVersion.Original; myParm = custDA.UpdateCommand.Parameters.Add("@oldCompanyName", SqlDbType.NVarChar, 30, "CompanyName"); myParm.SourceVersion = DataRowVersion.Original;

// Add the RowUpdated event handler. custDA.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);

DataSet custDS = new DataSet(); custDA.Fill(custDS, "Customers");

// Modify the DataSet contents.

custDA.Update(custDS, "Customers");

foreach (DataRow myRow in custDS.Tables["Customers"].Rows) { if (myRow.HasErrors) Console.WriteLine(myRow[0] + "\n" + myRow.RowError); }

protected static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs args){ if (args.RecordsAffected == 0) { args.Row.RowError = "Optimistic Concurrency Violation Encountered"; args.Status = UpdateStatus.SkipCurrentRow; }}

5.2.For ASP .Net

Optimistic concurrency control works by ensuring that the record being updated or deleted has the same values as it did when the updating or deleting process started. For example, when clicking the Edit button in an editable GridView, the record's values are read from the database and displayed in TextBoxes and other Web controls. These original values are saved by the GridView. Later, after the user makes her changes and clicks the Update button, the original values plus the new values are sent to the Business Logic Layer, and then down to the Data Access Layer. The Data Access Layer must issue a SQL statement that will only update the record if the original values that the user started editing are identical to the values still in the database.

Figure 2 depicts this sequence of events.

Page 5: White Paper On ConCurrency For PCMS Application Architecture

Figure 2: For the Update or Delete to Succeed, the Original Values Must Be Equal to the Current Database Values

The ADO.NET Typed DataSet provides one implementation that can be configured with just the tick of a checkbox. Enabling optimistic concurrency for a TableAdapter in the Typed DataSet augments the TableAdapter's UPDATE and DELETE statements to include a comparison of all of the original values in the WHERE clause.

For example:UPDATE Products SET ProductName = @ProductName, UnitPrice = @UnitPrice WHERE ProductID = @original_ProductID AND ProductName = @original_ProductName AND UnitPrice = @original_UnitPriceFor more details about this implementation, see http://www.asp.net/Learn/data-access/tutorial-21-cs.aspx

Page 6: White Paper On ConCurrency For PCMS Application Architecture

5.3. For Nhibernate:NHibernate has several concurrency models that you can use:

None Optimistic

o Dirty o All

Versioned o Numeric o Timestamp o DB timestamp

Pessimistic We will explore each of those in turn.None basically means that we fall back to the transaction semantics that we use in the database. The database may throw us out, but aside from that, we don’t really care much about things.Optimistic is more interesting. It basically states that if we detect a change in the entity, we cannot update it. Let us see a simple example of using optimistic dirty checking for changed fields only:<class name="Person"

optimistic-lock="dirty" dynamic-update="true" table="People">

Using this with this code:using (var session = sessionFactory.OpenSession())using (var tx = session.BeginTransaction()){

var person = session.Get<Person>(1);person.Name = "other";tx.Commit();

}Will result in:

Note that we have so specify dynamic-update to true. This is required because doing so will generally cause much greater number of query plan to exist in the database cache.Setting optimistic-lock to all would result in:

If the update fails because the row was updated, we will get a StaleObjectException. Like all exceptions, this will make the session ineligible for use, and you would have to create a new session to handle it.Usually a better strategy is to use an explicit version column. We can do it by specifying <version/>:

Page 7: White Paper On ConCurrency For PCMS Application Architecture

<version name="Version" column="Version"/>And that would result in:

As you can probably guess, if the version doesn’t match, we will get StaleObjectException.Instead of using numeric values, we can use a timestamp:<version name="Version" column="Version" type="timestamp"/>In this case, the property type should be DateTime, and the resulting SQL would be:

This is, of course, a less safe way of doing things, and I recommend that you would use a numeric value instead.Another option is to use the database facilities to handle that. in MS SQL Server, this is the TimeStamp column, which is a 8 byte binary that is changed any time that the row is updated.We do this by changing the type of the Version property to byte array, and changing the mapping to:<version name="Version"

generated="always" unsaved-value="null" type="BinaryBlob">

<column name="Version"not-null="false"sql-type="timestamp"/>

</version>Executing the code listed above will result in:

We use the value of the timestamp to ensure that we aren’t overwriting the row data after it was changed. The database will ensure that the row timestamp will change whenever the row itself is updated. This plays well with system where you may need to update the underlying tables outside of NHibernate.Pessimistic concurrency is also expose with NHibernate, by using the overloads that takes a LockMode. This is done in a database independent way, using each database facilities and syntax.For example, let us example the following code:using (var session = sessionFactory.OpenSession())

Page 8: White Paper On ConCurrency For PCMS Application Architecture

using (var tx = session.BeginTransaction()){

var person = session.Get<Person>(1,LockMode.Upgrade);person.Name = "other";tx.Commit();

}This will result in the following SQL:

We can also issue a separate command to the database to obtain a lock on the row representing the entity:using (var session = sessionFactory.OpenSession())using (var tx = session.BeginTransaction()){

var person = session.Get<Person>(1);session.Lock(person, LockMode.Upgrade);person.Name = "other";tx.Commit();

}The Get() would generate a standard select, without the locks, but the Lock() method would generate the following SQL:

The behavior for conflict in this case is very simple, we wait. If we wait for too long, the timeout will expire and we will get a timeout exception, because we could not obtain the lock.

5.4.For LINQ to SQL

LINQ to SQL supports optimistic concurrency control in great details.When an object is refreshed, the LINQ to SQL change tracker holds the following data:

The values originally taken from the database and used for the update check. The new database values from the subsequent query.

LINQ to SQL then determines whether the object is in conflict (that is, whether one or more of its member values has changed). If the object is in conflict, LINQ to SQL next determines which of its members are in conflict. Any member conflict that LINQ to SQL discovers is added to a conflict list. In the LINQ to SQL object model, an optimistic concurrency conflict occurs when both of the following conditions are true:

The client tries to submit changes to the database. One or more update-check values have been updated in the database since the client

last read them. Resolution of this conflict includes discovering which members of the object are in conflict, and then deciding what you want to do about it.

Page 9: White Paper On ConCurrency For PCMS Application Architecture

ChangeConflictException Class: Thrown when an update fails because database values have been updated since the client last read them.

5.4.1. Conflict Detection and Resolution Checklist

You can detect and resolve conflicts at any level of detail. At one extreme, you can resolve all conflicts in one of three ways (see RefreshMode) without additional consideration. At the other extreme, you can designate a specific action for each type of conflict on every member in conflict.

Specify or revise UpdateCheck options in your object model.

For more information, see How to: Specify Which Members are Tested for Concurrency Conflicts (LINQ to SQL).

In the try/catch block of your call to SubmitChanges, specify at what point you want exceptions to be thrown.

For more information, see How to: Specify When Concurrency Exceptions are Thrown (LINQ to SQL).

Determine how much conflict detail you want to retrieve, and include code in your try/catch block accordingly.

For more information, see How to: Retrieve Entity Conflict Information (LINQ to SQL) and How to: Retrieve Member Conflict Information (LINQ to SQL).

Include in your try/catch code how you want to resolve the various conflicts you discover.

For more information, see How to: Resolve Concurrency Conflicts by Retaining Database Values (LINQ to SQL), How to: Resolve Concurrency Conflicts by Overwriting Database Values (LINQ to SQL), and How to: Resolve Concurrency Conflicts by Merging with Database Values (LINQ to SQL).

5.4.2. Types That Support Conflict Discovery and Resolution

Classes and features to support the resolution of conflicts in optimistic concurrency in LINQ to SQL include the following:

System.Data.Linq . ObjectChangeConflict System.Data.Linq . MemberChangeConflict

System.Data.Linq . ChangeConflictCollection

System.Data.Linq . ChangeConflictException

DataContext . ChangeConflicts

DataContext . SubmitChanges

DataContext . Refresh

Page 10: White Paper On ConCurrency For PCMS Application Architecture

ColumnAttribute . UpdateCheck

System.Data.Linq.Mapping . UpdateCheck

System.Data.Linq . RefreshMode

6. Implementation of Pessimistic Concurrency:

In next version6.1.For .NetIn next version6.2.For ASP .NetIn next version6.3.For Nhibernate:In next version6.4.For LINQ to SQLIn next version

7. Reference:7.1. .Net

http://msdn.microsoft.com/en-us/library/aa0416cz(VS.71).aspx7.2.ASP .Net

www .asp.net/Learn/data-access/tutorial-21-cs.aspx http://www.eggheadcafe.com/articles/20050719.asp

7.3.LINQ 2 SQLhttp://msdn.microsoft.com/en-us/library/bb399373.aspxHow to: Detect and Resolve Conflicting Submissions (LINQ to SQL) Describes how to detect and resolve concurrency conflicts. How to: Specify When Concurrency Exceptions are Thrown (LINQ to SQL) Describes how to specify when you should be informed of concurrency conflicts. How to: Specify Which Members are Tested for Concurrency Conflicts (LINQ to SQL) Describes how to attribute members to specify whether they are checked for

concurrency conflicts. How to: Retrieve Entity Conflict Information (LINQ to SQL) Describes how to gather information about entity conflicts. How to: Retrieve Member Conflict Information (LINQ to SQL) Describes how to gather information about member conflicts. How to: Resolve Concurrency Conflicts by Retaining Database Values (LINQ to SQL) Describes how to overwrite current values with database values. How to: Resolve Concurrency Conflicts by Overwriting Database Values (LINQ to

SQL) Describes how to keep current values by overwriting database values. How to: Resolve Concurrency Conflicts by Merging with Database Values (LINQ to

SQL) Describes how to resolve a conflict by merging database and current values.

http://thedatafarm.com/blog/data-access/the-shadowy-side-of-linq-to-sql/ http://blogs.msdn.com/matt/archive/2008/05/22/into-to-linq-to-sql-optimistic-concurrency.aspxhttp://en.csharp-online.net/LINQ_to_ADO.NET%E2%80%94Optimistic_Concurrency_Database_Transactions

Page 11: White Paper On ConCurrency For PCMS Application Architecture

7.4.Nhibernate:http://nhforge.org/blogs/nhibernate/archive/2009/04/15/nhibernate-mapping-concurrency.aspxhttp://knol.google.com/k/fabio-maulo/nhibernate-chapter-10/1nr4enxv3dpeq/13#https://www.hibernate.org/hib_docs/nhibernate/html/transactions.html