Pragmatic Developer

Ali Özgür

Bookmark Blog

Add to Technorati Favorites

Google Talk

Chat with Ali Özgür

Purchase PragmaSQL from

Calendar

«  November 2008  »
MoTuWeThFrSaSu
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567
View posts in large calendar

Tag Cloud

Don't show

    Authors

    Recent Comments

    Banners




    aliozgur posted on September 22, 2008 14:07
    During evolution of .NET related technologies (almost lasted a decade) Microsoft published bunch of experimental technologies, frameworks and packages which caused developers to feel a little bit confused. This confusion made developers feel uncomfortable about the future of these technologies and we simply preferred, to the extent we can survive, not to use new .NET related stuff. We had the feeling that we were fighting to find our way out of a huge dust cloud, I think even Microsoft felt a little bit exhausted and as a result was late to set a clear vision for all these technologies. But with the release of .NET framework 3.0 and 3.5 it seems that Microsoft managed to settle down a clear vision about the future of .NET development. I think next decade (by 2010) we will talk/hear about and develop software based on the following .NET related technologies.

     


    Posted in: .NET Development  Tags:

    Currently rated 4.0 by 2 people

    • Currently 4/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Here is aother strange problem related with NHibernate

    The Problem

    I have a Parent class and two child classes Child1 and Child2 mapped to different tables on the database.
    Lets assume that we specified cascade='all' for child bags defined on Parent.hbm.xml. Sample workflow of instantiating parent and child objects is as the following

    - Create a parent object.
    - Insert 2 Child1 instances to child1 bag
    - Insert 3 Child2 instances to child2 bag.
    - Flush the session
    - Refresh parent object
    - We get 6 instances for each child bag (child1 and child2). But we expect 2 Child1 instances in child1 bag and 3 Child2 instances in child2 bag.

    Ther problem is : NHibernate performs left outer join on Child1 and Child2 tables when Refresh is called for the parent object. This is unaccaptable, I think NHibernate should initialize child collections with seperate selects commited to the database, or may be distinguish the duplicated child instances automatically in the collections. (using idbag instead of bag is not an option)

    Download the test case

    Requirements

    Watch This


    Posted in: .NET Development , C# , NHibernate  Tags:

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    I discovered this problem while developing a new system with the latest NHibernate.Burrow distribution (which in turn uses the latest NHibernate distribution). I spent some time Googling around to check if anyboy else met the same problem and found some entries but none of them specified exactly why this failure was happening and how we can solve this problem.

    The Problem

    My code simply executes the following steps

    1. Call a factory method
    2. Create a Curve
    3. Create CurveInterval objects
    4. Put CurveInterval objects inside the Curve.Intervals collection
    5. Call the same factory function to create another Curve instance
    6. Before creating Curve instance I perform some checks with HQL , this causes session to be flushed automaticaly
    7. I get the error when session is about to be flushed automatically

    001 <?xml version='1.0' encoding='utf-8'?> 
    002<hibernate-mapping xmlns='urn:nhibernate-mapping-2.2'> 
    003<class 
    004name='GradeEntry.Domain.Curve, GradeEntry.Domain' 
    005      table= 'LetterGrade'> 
    006<id name='Id' 
    007column='LG_ID' 
    008unsaved-value='0'> 
    009<generator class='native'/> 
    010</id> 
    011
    012<version name='ManagedVersion' column='NhVersion' type="System.Int64" unsaved-value="0"/> 
    013
    014<property name='DateCreated'/> 
    015<property name='CreatedByPersonId'/> 
    016<property name='Locked'/> 
    017<property name='LockChangedById' column ='LockChangedByID'/> 
    018<property name='LockChangedOn'/> 
    019<property name='LockMessage'/> 
    020<property name='LogIdx'/> 
    021<property name='LogCnt'/> 
    022<property name='IsStable'/> 
    023
    024<bag name='Intervals' 
    025order-by='LetterID asc' 
    026table='LetterGradeList' 
    027access='field.camelcase-underscore' 
    028inverse='true' 
    029cascade='delete-orphan, save-update' 
    030lazy='true'> 
    031<key column='LG_ID'/> 
    032<one-to-many class='GradeEntry.Domain.CurveInterval, GradeEntry.Domain' /> 
    033</bag> 
    034
    035<bag name='Log' 
    036order-by='Idx asc' 
    037table='LetterGradeLog' 
    038access='field.camelcase-underscore' 
    039inverse='true' 
    040cascade='delete-orphan,save-update' 
    041lazy='true'> 
    042<key column='LG_ID'/> 
    043<one-to-many class='GradeEntry.Domain.CurveLog, GradeEntry.Domain' /> 
    044</bag> 
    045
    046</class> 
    047</hibernate-mapping>
    048
    049
    050

     

    First Attempt To Reporoduce The Problem

    I have prepared a sample project but I was not able to recreate the bug, and I know it is hard to tell what is the problem under these conditions. But I have some more findings about this issue.

    - When I replace cascade of the bags to 'all-delete-orphan' from 'delete-orphan,save-update' everything is ok
    - When I replace cascade of the bags to 'all, delete-orphan' from 'all-delete-orphan' I still get the assertion failure.

    I think the problem is with the new implementation of cascade which is intended to support comma seperated list of cascade options.

    Second Attempt To Reporoduce The Problem

    After spending some more time trying to diagonise the problem I finally succeeded to reprouce the problem with atest case. I attached the test case.

    Simply the problem resolves to something like this.

    NOTE: All classes utilize managed versioning by defining ManagedVersion.

    1. I create 2 parent objects save them , flush the session and refresh them
    2. Then for each parent object I create some child objects of type Child1
    3. I perform HQL to get all Child3 instances. Child3 class does not have any association or cascade relation with Parent, Child1, Child2 and ParentRef classes. The HQL I performed causes the session to auto flush thus inserting Child1 instances to the database. But somehow while auto flushing the session versions of the parent objects are not updated. I expect two updates to be submitted to the database for parent objects since we associated Child1 instances with the parents and that must cause a version increment on parent objects.
    4. Then I try to perform another HQL query to get list of ParentRef objects and I get assertion failure. Note that ParentRef class is associated with Parent class which in turn defines cascade for Children1 and Children2 collections.

    If we do not perform the HQL in step 3 Child1 instances will be inserted to the database and parent objects will be updated while performing the HQL in step 4 and we will not get the assertion failure.

    I covered both cases in the attached test case.

    Database scripts are included under DBScript folder.

    Download test case

    Requirements

    Watch This

    See Also


    Posted in: .NET Development , C# , NHibernate  Tags:

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    I've already developed some projects with NHibernate and I can say that NHibernate is a real time saver. But I must admit that it takes some time to get used to NHibernate. As an ORM NHibernate has fantastic features but if you want to develop successfull projects with NHibernate you must know that NHibernate is only one part (ORM) of a successfull layered architecture. In the attached solution I tried to give you the basic idea of a layered architecture and how NHibernate can be used within such an architecture

    Attached solution includes the following projects

    • Core: Our domain objects (entities) reside in this layer. Also DAO (Data Access Objects) interfaces are defined in this layer.
    • DAL (Data Access Layer): Default implementation of DAO interfaces reside in this layer.
    • BLL (Business Logic Layer): Business logic code resides in this layer.
    • Common: Some utility calsses reside in this project
    • Tests.Disconnected: Includes unit tests for domain objects and business logic. Notice that unit tests in this project do not require domain objects to be persisted (NHibernate behaviour will not be tested), so the need for a database connection is eliminated which in turn makes our unit tests fast. Notice how we replaced our default DAL with mocked one.
    • Tests.Connected: This project includes unit tests too, but this time we want to test how our domain objects and bussiness logic perform NHibernate. NHibernate provides very cool features like native sql, lazy loading and cascading and we will likely want to test how our domain objects behave when armored with these cool features of NHibernate. It is also very likely that we will have some mapping errors (typos likely) in our Core, these tests will help us catch these errors. Performance bottlenecks possibly caused by our NHibernate mappings (for example we may discover that we need to make a child collection to be lazy loaded) can also be identified with help of these tests.

    In the sample solution you can also find a simple usage of Castle Windsor Inversion of Control (IoC) container. We use IoC to be able to load different implementations of our DAL (DAO implementations). 

    Another very important point you need to understand really well is session management of NHibernate when used in web applications. Thanks to Burrow contribution project this task is made very simple, you do not even need to write single line of NHibernate session management code. You only need to inherit your DAO implementation classes from GenericDao<T> class and you are ready to go. 

    Additional Notes

    • Database script is included in Tests.Connected project under DBScript folder. 
    • Sample project uses NHibernate  2.0 Aplha1 and NHibernate.Burrow is also Alpha1.
    • ASP .NET MVC Preview 3 to run Sales.MVC sample
    • TestDriven .NET to run NUnt tests

    Suggested Readings

    Downloads

    Update History

    • 09 June 2008
      • Castle files under Libs folder updated to Castle RC3
      • SQLite references removed
      • TestFixtureTearDown override of CustomTestBase class in Sales.Tests.Connected assembly commented out

    Posted in: NHibernate  Tags:

    Currently rated 4.8 by 4 people

    • Currently 4.75/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5