Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you do Versioning in Nhibernate?

I can't believe it is so hard to get someone to show me a simple working example. It leads me to believe that everyone can only talk like they know how to do it but in reality they don't.

I shorten the post down to only what I want the example to do. Maybe the post was getting to long and scared people away.

To get this bounty I am looking for a WORKING EXAMPLE that I can copy in VS 2010 and run.

What the example needs to do.

  1. Show what datatype should be in my domain for version as a timestamp in mssql 2008
  2. Show nhibernate automatically throwing the "StaleObjectException"
  3. Show me working examples of these 3 scenarios

Scenario 1

User A comes to the site and edits Row1. User B comes(note he can see Row1) and clicks to edit Row1, UserB should be denied from editing the row until User A is finished.

Scenario 2

User A comes to the site and edits Row1. User B comes 30mins later and clicks to edit Row1. User B should be able to edit this row and save. This is because User A took too long to edit the row and lost his right to edit.

Scenario 3

User A comes back from being away. He clicks the update row button and he should be greeted with StaleObjectException.

I am using asp.net mvc and fluent nhibernate. Looking for the example to be done in these.


What I tried

I tried to build my own but I can't get it throw the StaleObjectException nor can I get the version number to increment. I tired opening 2 separate browser and loaded up the index page. Both browsers showed the same version number.

public class Default1Controller : Controller
{
    //
    // GET: /Default1/

    public ActionResult Index()
    {
        var sessionFactory = CreateSessionFactory();

        using (var session = sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                var firstRecord = session.Query<TableA>().FirstOrDefault();
                transaction.Commit();
                return View(firstRecord);
            }

        }

    }

    public ActionResult Save()
    {
        var sessionFactory = CreateSessionFactory();
        using (var session = sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                var firstRecord = session.Query<TableA>().FirstOrDefault();
                firstRecord.Name = "test2";
                transaction.Commit();
                return View();
            }
        }
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2008
                .ConnectionString(c => c.FromConnectionStringWithKey("Test")))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<TableA>())
                             //  .ExposeConfiguration(BuidSchema)
            .BuildSessionFactory(); 
    }


    private static void BuidSchema(NHibernate.Cfg.Configuration config)
    {
        new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
    }

}


public class TableA
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }

    // Not sure what data type this should be for timestamp.
    // To eliminate changing to much started with int version
    // but want in the end timestamp.
    public virtual int Version { get; set; } 
}

public class TableAMapping : ClassMap<TableA>
{
    public TableAMapping()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        Version(x => x.Version);
    }
}
like image 351
chobo2 Avatar asked Sep 04 '12 23:09

chobo2


People also ask

What is the use of NHibernate?

NHibernate is Designed to serve as a persistence layer exclusively for the . Net framework based on Object-Relational Mapping Technique. A tool that creates a "virtual representation" of database objects within the code. Used to solve the problem of impedance mismatch between Class and relational databases and tables.

What is NHibernate session?

NHibernate is an open source object-relational mapper, or simply put, a way to rapidly retrieve data from your database into standard . NET objects. This article teaches you how to create NHibernate sessions, which use database sessions to retrieve and store data into the database.


1 Answers

Will nhibernate stop the row from being retrieved?

No. Locks are only placed for the extent of a transaction, which in a web application ends when the request ends. Also, the default type of transaction isolation mode is Read committed which means that read locks are released as soon as the select statement terminates. If you are reading and making edits in the same request and transaction, you could place a read and write lock on the row at hand which would prevent other transactions from writing to or reading from that row. However, this type of concurrency control doesn't work well in a web application.

Or would the User B be able to still see the row but if he tried to save it would crash?

This would happen if [optimistic concurrency] was being used. In NHibernate, optimistic concurrency works by adding a version field. Save/update commands are issued with the version upon which the update was based. If that differs from the version in the database table, no rows are updated and NHibernate will throw.

What happens if User A say cancels and does not edit. Do I have to release the lock myself or is there a timeout can be set to release the lock?

No, the lock is released at the end of the request.

Overall, your best bet is to opt for optimistic concurrency with version fields managed by NHibernate.

like image 136
eulerfx Avatar answered Oct 12 '22 12:10

eulerfx