These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 25 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Optmisitic Concurrency for Many sessions with auto. versioni
PostPosted: Thu Nov 09, 2006 6:18 am 
Regular
Regular

Joined: Thu Aug 24, 2006 2:05 am
Posts: 80
Hi All,

Optimistic concurrency for "Many sessions with automatic versioning" approach is not working in the implemented application

Approach: For each call to perfrom any of the CRUD operation, application opens new ISession connection, perfroms the task and closes the connection.

Scenerio:
1. Read the same object( let's say Object A) by two functions.
2. Function 1 perfroms some modification on the Object A, opens the ISession connection, updates the same OBject using ISession.Update(ObjectA) function and closes the connection.
3. Now Function 2 contains stale object. Funcion 2 perfroms some modification on the Object A, opens the connection, now tries to update the Object A using ISession.Update(ObjectA) function. As ObjectA contains stale data so it should have been failed but it succeeded(I dont know why?).

So please let me know I am missing something in the mapping file or any settings?

Also please let me know "How nHibernate maintains internal timestamp/version to support Optimistic Concurrency?"

Please please let me know the solution(Its Urgent)...

Thanks in Advance,
Deepak


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 09, 2006 7:02 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Do you ever call Flush()?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 09, 2006 9:10 am 
Regular
Regular

Joined: Thu Aug 24, 2006 2:05 am
Posts: 80
Yes, flush() has been called.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 12, 2006 3:24 pm 
Regular
Regular

Joined: Thu Aug 24, 2006 2:05 am
Posts: 80
If anybody knows exact working of nhibernate optimistic concurrency then please plse do let me know.
I am very clear about explicit timestamp based Opt. conc. approach but when I tried nHibernate internal approach for O.C. then it fails.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 13, 2006 3:26 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Show the code (a small sample) that is not working and somebody will tell you what the problem is.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 13, 2006 4:19 am 
Regular
Regular

Joined: Thu Aug 24, 2006 2:05 am
Posts: 80
Code snippet is given as below:

Code:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using nHibernateEval.BusinessEntities;
using NHibernate;

namespace nHibernateEval.NHibernate
{
    /// <summary>
    /// This class is used to perform CRUD operation. It is also used to check the
    /// nHibernate support for optmistic concurrency with many ISession
    /// object .
    /// </summary>
    public class GenericDAO
    {
        #region Member variables.
     
/// <summary>
        /// It is used to retrieve the business entity.
        /// </summary>
        /// <param name="entityType">business entity type.</param>
        /// <param name="id">primary key.</param>
        /// <returns>returns business entity object.</returns>
        /// <returns></returns>
        public object ConcurrencyOprnWithMultiSession_Get(Type entityType, int id)
        {
            try
            {
                session = NHibernateSessionFactory.OpenSession();
                               
                object patientObj = session.Get(entityType, id);
                session.Close();
                return patientObj;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Function is used to perform concurrency operation using multi ISession object.
        /// It is used to retrieve the business entity.
        /// </summary>
        /// <param name="obj">business entity object.</param>
        /// <returns>returns true on successful entity updatation.</returns>
        public bool ConcurrencyOprnWithMultiSession_Update(object entity, out string errorMsg)
        {
            errorMsg = string.Empty;
            try
            {
                //Creates new session which will be used to perform db operations.
                session = NHibernateSessionFactory.OpenSession();
                session.SaveOrUpdate(entity);
                session.Flush();
                session.Close();
            }
            catch (Exception expn)
            {
                errorMsg = expn.Message;
                return false;
            }
            return true;
        }

      #endregion Method

    }
}


//Calling function

/// <summary>
        /// Used to depict nHibernate support for Optimistic Concurrency
             with  Session object for each database request.
        /// </summary>
        /// <param name="errorMsg">Optimistic Concurrency error
        ///     message.</param>
        /// <returns>returns true if tested successfully.</returns>
        public bool CheckOptConcurrencyWithMultiSession( out string errorMsg)
        {
            int patID = 2;
            bool result = false;
            errorMsg = string.Empty;

            GenericDAO crudOprn = new GenericDAO();

            //Retrieves same patient object by two patient objects.
            object pat1 = crudOprn.ConcurrencyOprnWithMultiSession_Get(typeof(Patient), patID);
            object pat2 = crudOprn.ConcurrencyOprnWithMultiSession_Get(typeof(Patient), patID); ;

            if (pat1 != null && pat2 != null)
            {
                Patient patient1 = (Patient)pat1;
                Patient patient2 = (Patient)pat2;

                //Update Patient1.LastName
                patient1.LastName = "Update";
                result = crudOprn.ConcurrencyOprnWithMultiSession_Update
(patient1, out errorMsg);

                //Now Patient2 contains stale data because Patient1 has already updated
                //the Patient lastname. Now update ConcurrencyOprnWithMultiSession_Update
                //should throw an exception.
                patient2.LastName += "Stale Update";
                result = crudOprn.ConcurrencyOprnWithMultiSession_Update(patient2, out errorMsg);
                string closeConnErrorMsg = string.Empty;
                crudOprn.CloseSession(out closeConnErrorMsg);
            }
            return result;
        }

//Mapping XML File


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="nHibernateEval.BusinessEntities.Patient,nHibernateEval.BusinessEntities" table="Patient" lazy="true">

               <id name="Id" column="ID" type="Int32" unsaved-value="0">
         <generator class="identity"/>
   </id>
   <bag name="PrescriptionList" cascade="all" inverse="true"
                   lazy="true" >
   <key column="PatientID" />
   <one-to-many 
class="nHibernateEval.BusinessEntities.Prescription,nHibernateEval.BusinessEntities" />
   </bag>
   <property column="OrgID" type="Int32" name="Orgid" not-null="true" />
   <property column="ScopeID" type="Int32" name="Scopeid" not-null="true" />
   <property column="timestamp" type="System.Byte[]" name="Timestamp" not-null="true" update="false" insert="false"/>
   <property column="FirstName" type="String" name="FirstName" length="50" />
   <property column="MiddleName" type="String" name="MiddleName" length="50" />
   <property column="LastName" type="String" name="LastName" not-null="true" length="50" />
   <property column="DOB" type="System.DateTime" name="Dob" />
   <!--<property column="DOB" type="DateTime" name="Dob" />-->
   <property column="Gender" type="nHibernateEval.BusinessEntities.GenderEnumType,nHibernateEval.BusinessEntities" name="Gender" not-null="false" length="1" />
   <property column="SSN" type="String" name="Ssn" length="11" />
   <many-to-one name="PrimaryCarePhysicianid" column="PrimaryCarePhysicianID" class="nHibernateEval.BusinessEntities.Doctor,nHibernateEval.BusinessEntities" cascade="all"/>
   <many-to-one name="HomeAddressid" column="HomeAddressID" class="nHibernateEval.BusinessEntities.Address,nHibernateEval.BusinessEntities" cascade="all"/>
   <property column="HomePhone" type="String" name="HomePhone" length="50" />
   <many-to-one name="WorkAddressid" column="WorkAddressID" class="nHibernateEval.BusinessEntities.Address,nHibernateEval.BusinessEntities" cascade="all"/>
   <property column="WorkPhone" type="String" name="WorkPhone" length="50" />
</class>
</hibernate-mapping>



Please let me know if you need more clarification of the above sample code.

Thanks,
Deepak


Last edited by deepakbadki on Wed Nov 15, 2006 3:45 am, edited 2 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 13, 2006 5:59 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
As long as You obtain same object trough one session, the object instances should be identical. i.e. object.ReferenceEquals()

Have You checked what data does the patietn2 holde before You chnage it?


Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 13, 2006 6:23 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Quote:
Please let me know if you need more clarification of the above sample code.


First, it would really help if the code was formatted properly, use code tag to do it.

Second, the smaller the example is, the more chance there is that somebody will find a problem in it and tell you exactly what it is. The sample you posted is way too big to look into in detail.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 15, 2006 3:50 am 
Regular
Regular

Joined: Thu Aug 24, 2006 2:05 am
Posts: 80
Hi Sergey,

Sorry for the late reply as I was busy with other nHibernate stuff.
Code is formated now. Whenever you will find free time then please reply me with the solution for the same.

Thanks,
Deepak


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 15, 2006 4:08 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
I don't see neither a version column, nor a timestamp column in your mapping, and the class is not mapped with optimistic-lock="all" or "dirty" either, so optimistic locking is not enabled for the class at all.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 15, 2006 4:47 am 
Regular
Regular

Joined: Thu Aug 24, 2006 2:05 am
Posts: 80
Thanks for the quick reply.
My understanding is "In case of Optimistic Concurrency across multiple sessions, there is no need of explicit timestamp column(Correct me if wrong?), nHibernate internally manages the Optimistic Concurrency."

Please let me know if timestamp column is must in Optimistic Concurrency across multiple sessions.

Waiting for reply
-Deepak


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 15, 2006 4:51 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
This is wrong. Where have you got that understanding from?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 15, 2006 5:47 am 
Regular
Regular

Joined: Thu Aug 24, 2006 2:05 am
Posts: 80
Hi Sergey,

Thanks for your reply!

As per my understanding (after reading the documentation), "Long session with automatic versioning" and "Many sessions with automatic versioning" do not require timestamp column. Nothing has been mentioned about timestamp column in the documentation for these approaches.

I tried both these approaches without timestamp column and the first one ("Long session with automatic versioning") worked. But the second approach failed ("Many sessions with automatic versioning").

I need to know:
1)
i) Do I need to have a timestamp column for "Many sessions with automatic versioning" approach?
ii) If timestamp is to be used, do I need to explicitly check the timestamp in my code or nHibernate does the check by adding the timestamp in the where clause?
iii) What should be the timestamp datatype in my SQL-Server database and C#.Net application?

2) Really, I am looking for the best approach supported by nHibernate for optimistic concurrency control across sessions. By this I mean, I am not going to maintain a single ISession object for my application. What is the recommended approach for this kind of architecture and how can I implement that? :)

Thanks for your help.

Regards,
Deepak


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 15, 2006 6:01 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
i) You have to have a timestamp or a version column.
ii) NHibernate checks it itself but you can also force the check, this is explained in the docs.
iii) If it is a version column, it should be an integer (any size will do). If it is a timestamp, it should be date/time. SQL Server-specific "timestamp" type will not work.

2) - the recommended approach is to add a version property to your objects.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 15, 2006 7:02 am 
Regular
Regular

Joined: Thu Aug 24, 2006 2:05 am
Posts: 80
Hi Sergey,

Thanks for the help !
Still implicit version check @my end doesn't work.

Scenario:
1. Get the same Patient record in two Patient Objects( les's say Pat A & B)
2. Do some modification on Pat A and update it.
3. Now Pat B contains stale data. Do some modification on Pat B and try to update it. Update should fail but it works :(

optimistic-lock="all" and version column is added in Patient.hbm.xml file.
Is there any setting needs to be done in order to perform implicit version check?


Sample code is given as below:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
   <class name="MyApp.BusinessEntities.Patient,MyApp.BusinessEntities" table="Patient" lazy="true" dynamic-update="true" optimistic-lock="all">

      <id name="Id" column="ID" type="Int32" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <version column="TimeStamp" name="TimeStamp"/>
      <bag name="PrescriptionList" cascade="all" inverse="true">
         <key column="PatientID" />
         <one-to-many class="MyApp.BusinessEntities.Prescription,MyApp.BusinessEntities" />
      </bag>
      <property column="FirstName" type="String" name="FirstName" length="50" />
      <property column="MiddleName" type="String" name="MiddleName" length="50" />
      <property column="LastName" type="String" name="LastName" not-null="true" length="50" />
      <property column="DOB" type="System.DateTime" name="Dob" />
      <property column="Gender" type="MyApp.BusinessEntities.GenderEnumType,MyApp.BusinessEntities" name="Gender" not-null="false" length="1" />
      <property column="SSN" type="String" name="Ssn" length="11" />
      <many-to-one name="PrimaryCarePhysicianid" column="PrimaryCarePhysicianID" class="MyApp.BusinessEntities.Doctor,MyApp.BusinessEntities" />
      <many-to-one name="HomeAddressid" column="HomeAddressID" class="MyApp.BusinessEntities.Address,MyApp.BusinessEntities" />
      <property column="HomePhone" type="String" name="HomePhone" length="50" />
      <many-to-one name="WorkAddressid" column="WorkAddressID" class="MyApp.BusinessEntities.Address,MyApp.BusinessEntities" />
      <property column="WorkPhone" type="String" name="WorkPhone" length="50" />
   </class>
   <sql-query name="PrescriptionList">
      <load-collection alias="prescription" role ="MyApp.BusinessEntities.Patient.PrescriptionList"/>
      exec PrescriptionList ?
   </sql-query>
</hibernate-mapping>


Code:

//Calling Function
private void button4_Click(object sender, EventArgs e)
{
MyApp.DataAccess.DbOperations crudOpern = new DbOperations();
            Patient patientObj11 = (Patient)crudOpern.Read(1, typeof(Patient));
            Patient patientObj21 = (Patient)crudOpern.Read(1, typeof(Patient));
            patientObj11.LastName = "Update1";
            crudOpern.Update(patientObj11);
            patientObj21.LastName = "Update2";
            crudOpern.Update(patientObj21);
}


//Called Funcion

        public object Read(object dataObj, Type objType)
        {
            try
            {
                session = NHibernateSessionFactory.OpenSession();
                object obj = session.Get(objType, dataObj);
                session.Close();
                return obj;
            }
            catch (Exception)
            {
                if (session.IsOpen)
                    session.Close();
                return null;
            }
        }

public bool Update(object obj)
        {
            try
            {
                session = NHibernateSessionFactory.OpenSession();
                ITransaction transaction = session.BeginTransaction();
                session.SaveOrUpdate(obj);
                session.Flush();
                transaction.Commit();
                session.Close();
                return true;
            }
            catch (Exception expn)
            {
                if (session.IsOpen)
                    session.Close();
                return false;
            }
        }



Thanks,
Deepak


Last edited by deepakbadki on Thu Dec 07, 2006 5:52 am, edited 1 time in total.

Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 25 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.