4. Transactions and Concurrency
nhiberate provides its own ITransaction abstraction
the goal of nhibe is to abstract the choice of databse engine for you. so you dont need to worry about how the db imlements transactions, nhibe will do it for you.
Transaction Pattern
ask the ISession to begin a transaction
do some work
commit or rollback the transaction[csharp]
ITransaction tx = session.BeginTransaction();
//do some work
tx.Commit();
// or tx.Rollback();
[/csharp]
real world is a bit more complex[csharp]
using(ITransaction tx = session.BeginTransaction())
{
try {
//do some work
tx.Commit();
}
catch(NHibernateException) {
tx.Rollback();
throw;
}
}
[/csharp]
when shold you use transactions? Aways! - even on reads (queries)
you have no idea why a db operation may have failed, so instead or worrying, just implement transactions..
before we start we need a refactor of our dataaccess layer. we have a private global session
this is not a great design strategy
the session is not made to be hung on to for a long time
it is non thread safe use once and throw away
the session factory however is much stronger use once
so.. we change the private ISession to an ISessionFactory[csharp]
public class DataAccessProvider
{
private ISessionFactory sessionFactory;
//we now call the getsession in the constructor to the class..
public DataAccessProvider ()
{
sessionFactory = GetSessionFactory();
}
private static ISession GetSession()
{
return sessionFactory.OpenSession();
}
private static ISession GetSessionFactory()
{
return (new Configuration()).Configure().BuildSessionFactory();
}
[/csharp]
now our methods become like:[csharp]
public void AddCustomer(Customer customer)
{
ISession session = GetSession();
session.Save(customer); //save will return an object that represents the primary key of that object in the database
session.Flush();
}
[/csharp]
now each method will use its own copy of the session (not perfect, we will move on again later in the lessons..[csharp]
[test]
[ExpectedException(typeof(NHibernate.HibernateException))]
public void DeleteCustomerCanThrowExceptionOnFail()
{
Customer c = GetFirstCustomerWithOrders();
provider.DeleteCustomer(c);
}
[/csharp]
now, how can we refactor the delete customer method to take advantage of transactions..[csharp]
public void DeleteCustomer(Customer c)
{
using(ISession session = GetSession()) {
using(ITransaction tx = session.BeginTransaction()) {
try {
session.Delete(c);
session.Flush();
tx.Commit();
}
catch(NHibernateException) {
tx.Rollback();
throw;
}
}
}
}
[/csharp]
Concurrency
what does it mean? 2 or more users may be editing hte same data at the same time..
this especially happens in a disconnected-data world
types of concurrency:
Pessimistic concurrency
something in the overall system is responsible for actively blocking operations that could result in data-synchronisation conflicts
Pessimistic (assume something is going to go badly and actively block it from happening)
usually accomplished by exclusive locks approach - Expensive!
Optimsitic Concurrency
assumes no operations that could result in data-synchronisation conflicts will occur and is reposinsible for reacting properly when they do
similar to edit, merge, comit with todays source control, unlike old source control with exclusive locks..
NHibernate Optimistic Concurrency
several approaches
in the approriate hbm.xml mapping file, add a <version> element (implementation of row versioning)
or a <timestamp> element (implementation of timestamp tracking)
and several others..
in general, row versioning is preferred
the version tag must precede any property tags in the mapping file
assuming we have added an integer proeprty called version to customer class[xml]
<version name="Version" column="Version" type="integer" unsaved-value="0" />
[/xml]
now in the database, when you add the version column, no nulls, default value is 1
nhiberate provides its own ITransaction abstraction
the goal of nhibe is to abstract the choice of databse engine for you. so you dont need to worry about how the db imlements transactions, nhibe will do it for you.
Transaction Pattern
ask the ISession to begin a transaction
do some work
commit or rollback the transaction[csharp]
ITransaction tx = session.BeginTransaction();
//do some work
tx.Commit();
// or tx.Rollback();
[/csharp]
real world is a bit more complex[csharp]
using(ITransaction tx = session.BeginTransaction())
{
try {
//do some work
tx.Commit();
}
catch(NHibernateException) {
tx.Rollback();
throw;
}
}
[/csharp]
when shold you use transactions? Aways! - even on reads (queries)
you have no idea why a db operation may have failed, so instead or worrying, just implement transactions..
before we start we need a refactor of our dataaccess layer. we have a private global session
this is not a great design strategy
the session is not made to be hung on to for a long time
it is non thread safe use once and throw away
the session factory however is much stronger use once
so.. we change the private ISession to an ISessionFactory[csharp]
public class DataAccessProvider
{
private ISessionFactory sessionFactory;
//we now call the getsession in the constructor to the class..
public DataAccessProvider ()
{
sessionFactory = GetSessionFactory();
}
private static ISession GetSession()
{
return sessionFactory.OpenSession();
}
private static ISession GetSessionFactory()
{
return (new Configuration()).Configure().BuildSessionFactory();
}
[/csharp]
now our methods become like:[csharp]
public void AddCustomer(Customer customer)
{
ISession session = GetSession();
session.Save(customer); //save will return an object that represents the primary key of that object in the database
session.Flush();
}
[/csharp]
now each method will use its own copy of the session (not perfect, we will move on again later in the lessons..[csharp]
[test]
[ExpectedException(typeof(NHibernate.HibernateException))]
public void DeleteCustomerCanThrowExceptionOnFail()
{
Customer c = GetFirstCustomerWithOrders();
provider.DeleteCustomer(c);
}
[/csharp]
now, how can we refactor the delete customer method to take advantage of transactions..[csharp]
public void DeleteCustomer(Customer c)
{
using(ISession session = GetSession()) {
using(ITransaction tx = session.BeginTransaction()) {
try {
session.Delete(c);
session.Flush();
tx.Commit();
}
catch(NHibernateException) {
tx.Rollback();
throw;
}
}
}
}
[/csharp]
Concurrency
what does it mean? 2 or more users may be editing hte same data at the same time..
this especially happens in a disconnected-data world
types of concurrency:
Pessimistic concurrency
something in the overall system is responsible for actively blocking operations that could result in data-synchronisation conflicts
Pessimistic (assume something is going to go badly and actively block it from happening)
usually accomplished by exclusive locks approach - Expensive!
Optimsitic Concurrency
assumes no operations that could result in data-synchronisation conflicts will occur and is reposinsible for reacting properly when they do
similar to edit, merge, comit with todays source control, unlike old source control with exclusive locks..
NHibernate Optimistic Concurrency
several approaches
in the approriate hbm.xml mapping file, add a <version> element (implementation of row versioning)
or a <timestamp> element (implementation of timestamp tracking)
and several others..
in general, row versioning is preferred
the version tag must precede any property tags in the mapping file
assuming we have added an integer proeprty called version to customer class[xml]
<version name="Version" column="Version" type="integer" unsaved-value="0" />
[/xml]
now in the database, when you add the version column, no nulls, default value is 1
No comments:
Post a Comment