Category Archives: NHibernate

When first starting NH mapping, we just want to make sure the data is really being deleted, for cascaded child, some tricky code are needed to work around the strong relationship we created in domain entities. SqlQuery is one of those.


[Test]
 public void Should_delete_email()
 {
 // Retrieve
 Organization org = _repository.FetchById(8172);

 // Ensure org was retrieved.
 Assert.That(org, Is.Not.Null);

 var emailToAdd = new Email("Home Alternate", "x@y");
 org.AddEmail(emailToAdd);

 _repository.Update(org, org.LastModifiedDate);
Assert.That(emailToAdd.Id == 0);
_session.Flush();
Assert.That(emailToAdd.Id > 0);

 // Delete
 org.DeleteEmail(emailToAdd);
 _session.Flush();

 // Ensure email data is physically deleted
 ISQLQuery query = _session.CreateSQLQuery("select * from Stakeholder_Email_CV where stakeholder_email_id = " +
 emailToAdd.Id);
 Assert.That(query.List().Count == 0);

 }

Quite interesting testing code for NHibernate mapping.

I’m slowly adopting Grey Young’s recent topic of CQS – Command Query Separation, sometimes we don’t need a rich domain object for very simple purpose. Most people call it as DTO. Those ‘DTO’ don’t need mapping file. Because they are not translated from domain object, instead they can be ‘transformed’ from NHibernate SQLQuery.

Ayende has an example of SQLQuery using AliasToBeanResultTransformer, here is another example of  PositionalToBeanResultTransformer from Gustavo, which needs add query into mapping file.

I like to keep query out of mapping file, adopt AliasToBeanResultTransformer:


public OrganizationAuditD FindByOrgIdAndAction(long id, string changCode)
 {
 IQuery query = Session.CreateSQLQuery(
 @"select a_Su_Id from dbo.z_Organization_AV  where a_Stakeholder_Id = :id and a_change_code = :changCode")
 .AddScalar("a_Su_Id", NHibernateUtil.String)
 .SetInt64("id", id)
 .SetString("changCode", changCode)
 .SetResultTransformer(new AliasToBeanResultTransformer(typeof(OrganizationAuditD) ))
 ;

 return query.List<OrganizationAuditD>()[0];
 }

My OrganizationAuditD DTO only has one meaningful property: a_Su_Id, that all I need. No other domain property / behavior at all.

Two solutions available for paging fetch result:

  1. SetFirstResult/SetMaxResult when using NHibernate detached queies. Ayende has a good example.
  2. Skip()/Take() when using NHibernate.Linq

I personally like the latter because it’s strongly typed. Performance are same, both with TOP(N) in the generated SQL.

Only issue remaining, how to pass the total count back to service/UI? Options

  1. Using out parameter keyword, as this example.
  2. Create my own Page<T> class to organize the fetch result, similar to the Pager class in Karl’s ModelQuery

Code:  (This one has a double query problem)


public Page<Organization> FetchOrganizationWithNameContains(string orgNamePart
   , int indexOfPage, int resultsPerPage)
{
    var result = new Page<Organization>();

    var query = Session.Linq<Organization>().Where(x => x.Name.Contains(orgNamePart));

    result.Entities = query.Skip((indexOfPage - 1)*resultsPerPage)
        .Take(resultsPerPage).ToArray();

    result.TotalCount = query.Count();

    return result;
 }

We have an inheritance tree like this:

StakeholderClassDiagram

Each class has a mapping table in database, one thing we (or our DBA) did wrongly is that both Inidividual and Organization tables have their own timestamp fileds. This caused a big problem when we were tring to follow the per-table-per-inheritance mapping example from NHibernate in Action book. Eventually, we had to treat those common fields from BaseStakeholder as a component like part in separated Individual and Organization mapping files, using the join syntax:

<class name=Individual table=Individual_CV >
<
id name=Id column=Stakeholder_ID unsaved-value=0 >
<
generator class=identity />
</
id>
<
timestamp column=S_Datename=LastModifiedDategenerated=alwaysunsaved-alue=undefined/>

<property column=Gender type=string name=Gender not-null=true />

<bag name=Emailsaccess=field.camelcase-underscorelazy=truecascade =all-delete-orphan
inverse=trueoptimistic-lock=false>
<
key column=Stakeholder_ID foreign-key=Stakeholder_ID />
<
one-to-many class=Email />
</
bag>

<join table=Stakeholder_CV >
<
key column=Stakeholder_ID />
<
property column=Stakeholder_Type type=String name=StakeholderType not-null=true length=50 />
<
property column=Expired type=String name=Expired not-null=true length=3 />
<
property column=Last_Approval_Date type=DateTime name=LastApprovalDate not-null=true />
</
join>
</
class>

Duplication is unavoidable, until we move to Fluent NHibernate.

There is another trick in this inheritance mapping. We want to do bidirectional one-to-many mapping due to the not-null foreign key policy in our database, that’s why we set inverse=trueto Email property. But in Email.hbm.mapping, how can we map back to right type of stakeholder, instead of the virtual/abstract BaseStakeholder? Any keyword does the trick, but we need to move the StakeholderType field into email table/view to meet the requirements.

<class name=Email table=Stakeholder_Email_CV >

<any name=Stakeholder id-type=System.Int64 meta-type=System.String>
<
meta-value class=Individual value=Individual/>
<
meta-value class=Organization value=Organization/>
<
column name=Stakeholder_Type/>
<
column name=Stakeholder_Id/>
</
any>

Again, this mapping part has to be duplicated in every mapping files of child class, like phone number, address, etc. How can FluentNHiberate also fix this issue?

NOTE: This solution doesn’t work with latest version of Fluent NHibernate. I created a patch to enable you can use stored procedure in RTM version (r647).   As they mentioned in FN google group, this patch will go into trunk in a few days.

New syntax:

SqlInsert(INSERT_SP).Check.None();
SqlUpdate(UPDATE_SP).Check.None();
SqlDelete(DELETE_SP).Check.None();

Ryan’s solution is a very high level usage of Fluent NHibernate. By creating a customized StoredProcedurePart class implementing IMappingPart interface, developer gained some kind of control to merge their Stored Procedure definition into FN mappings.

A useful trick:

Export hbm file to somewhere say temp folder for debug purpose, you don’t trust any new guys.


            var config = Fluently.Configure()
                .Database(
                MsSqlConfiguration.MsSql2005
                    .ConnectionString(x =&gt; x.FromConnectionStringWithKey(connectionStringKey))
                    .ShowSql()
                    .ProxyFactoryFactory(&quot;NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle&quot;)
                )
                .Mappings(m =&gt; m.FluentMappings.AddFromAssemblyOf&lt;T&gt;()
                                   .ExportTo(Path.GetTempPath())
                )
                ;

I had to add sql-insert, sql-update, sql-delete into XmlHibernateMappingWriter.sorting Dictionary. The reason of applying this patch is: the current sorting xml children logic in FN (r479) has a bug when comparing two many undefined elements.

if (!sorting.ContainsKey(x.Name) || !sorting.ContainsKey(y.Name)) return 0;
e.g.
it was pre-defined that definded-element-A is less than definded-element-B, but if we introduced an un-defined-element-C,
ContainsKey check in sorting children method will say:
definded-element-A == un-defined-element-C,
and
un-defined-element-C ==definded-element-B,
this will result
definded-element-A == definded-element-B!

In my case, all the properties were bubbled up to first level and caused a strange System.Xml.Schema.XmlSchemaValidationException.

The current version of Fluent NHibernate (r479) doesn’t support Sql-insert, sql-update, sql-delete.

FN can do mixed configuration, as example:

Fluently.Configure()
  .Database(configurer)
  .Mappings(m =>
  {
    m.FluentMappings.AddFromAssemblyOf<UserCreator>();
    m.HbmMappings.AddFromAssemblyOf<UserCreator>(); // loads the embedded
resources
  })
  .ExposeConfiguration(BuildSchema)
  .BuildSessionFactory();

But I can’t use this patten to partly mapping properties on the same entity using FN, and use classic hbm to implement SP.

I must work on a horrible legacy db.

  • One table per hierarchy inheritance can all use the sql-insert, update, delete declaration in root mapping file.
  • Duplicate property is not allowed in mapping file, including those key columns in composite-id section. We were having ‘extra update when inserting’ and ‘Invalid Index N for this SqlParameterCollection with Count=N error’, both are caused by this new restriction. By removing the duplication, problem solved.
  • The Restrictions static class (used call Expression?) can only access those field defined in mapping file, before it can access all properties in class, does not matter it’s in mapping or not.

1. Set NoCount OFF

Updatable SP needs to turn Set NoCount OFF, NH is very peaky to the response from SP action. Here is an post in Chinese whose example has the line Set NoCount ON in SP commented out. One of the possible problem will be “NHibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect”

According to NH doc:

The stored procedures are by default required to affect the same number of rows as NHibernate-generated SQL would. NHibernate uses IDbCommand.ExecuteNonQuery to retrieve the number of rows affected. This check can be disabled by using check="none" attribute in sql-insert element.

2. Concurrency Check

Timestamp should be placed on top of the property list and right after id/composite id section. Repository/DAO class can then use “session.Lock(attribute, LockMode.Read)” to do concurrency check, throw staleObjectStateException when timestamp doesn’t match.

LockMode.Read just checks version column. It’s a very good solution when using DTO pattern to apply changs from DTO back to domain model. DTO should always carry a original timestamp field, we can do dirty check in service layer before apply changes, but it will be much easier to put the following code into baseRepository:

     <version
             name="LastModifiedDate"
             type="timestamp"
             column="S_Date"
     />
public override void SaveOrUpdate(T objToSave)
 {
 // Do not check new objects.
 ConcurrencyCheck(objToSave);

 try
 {
 base.SaveOrUpdate(objToSave);
 }
 catch (Exception ex)
 {
 HandleDatabaseException(ex);
 }

 return;
 }

private void ConcurrencyCheck(T obj)
 {
 if (IsNew(obj)) return;

 if (WasTimeStampCachedBefore())
 {
 if (IsTimeStampChanged(obj))
 throw new ConcurrencyException();

 // Don't try to lock an object with Id. All kinds of exceptions:
 //  1. reassociated object has dirty collection
 return;
 }

 // if we didn't cache timestamp
 try
 {
//                Session.Evict(obj); // Evict will disable update
//                Session.Lock(obj, LockMode.Read);
 using (var session = NHibernateFactory.OpenSession())
 {
 session.Lock(obj, LockMode.Read);
 }
 }
 catch (StaleObjectStateException)
 {
 throw new ConcurrencyException();
 }
 }
        [Test]
        [ExpectedException(typeof(InfrastructureException))]
        public void should_throw_stale_exeption_for_dirty_data()
        {
            var session1 = NHibernateFactory.OpenSession();
            var repository1 = new AttributeRepository(new InMemorySessionStorage(session1));

            var attribute = repository1.FetchByTypeAndCode("003", 8);

            // apply changes from DTO
            attribute.Description = "test data " + new Random().Next();

            // DTO might contains older timestamp
            attribute.LastModifiedDate = ((DateTime) attribute.LastModifiedDate).AddSeconds(-8);

             _repository.SaveOrUpdate(attribute);
        }

Note:  TimeStamp in SQLServer == dotnet Byte[]
Version/TimeStamp in NHibernate == dotnet Datetime  (Datetime if set unsaved-value=nullable)

I added Flush and Evict before Lock to fix the errors of “collection binding to two open sessions” and “child association dirty” problem. Thanks to this post.

Somebody worked very hard to make NHibernate support db.TimeStamp by introducing UserType. Thanks God we don’t have any timestamp in our db.

Notice I could just do a version check out of repository, say service layer, check version number right after retrieve and before applying changes from DTO, as shown in this post 10.4.3 . The idea is similar, and more efficiency actually, only one drawback is that code can’t push down to a base class.

3. Composite Id

Composite Id can be done through a component serializable class overriding Equals and GetHashCode methods.if not using version/timestamp column, unsaved-value should set to any instead of none,    to check it’s a new object when doing SaveOrUpdate().
sql-insert, update, delete section can split to mulit-lines with “–” as the comment tag to filter out unused properties by SP.Or just use @p0, @p1, @p2 directly instead of using ?,?,?

To CSLA or Not CSLA – Your Thoughts? People with CSLA experience are talking.

There is failed experience with CSLA and Magenic as well.

People are trying to use CSLA with NHibernate. In which the only comment seems reverse, I am doing the same thing, passing DTO between DAL and BO. Somebody even used CSLA + NHibernate + CAB/SCSF.

There is another guy doing CSLA + NHibernate, don’t know the result yet.

Some people are using CSLA + subsonic. no detail info available.

This guy, Patrick, is also using CSLA + NHiernate, his project layout is very interesting. Patrick is also using MVP pattern with CSLA, can wait to see his example code for this. In fact, what Patrick is working on is an open source project called Domain Builder on code plex.

Rocky’s response to CSLA + DAL:

CSLA .NET is not an object-relational mapping technology. I have very specifically avoided ORM concepts in the framework, in the hopes that someone (like Microsoft) would eventually provide an elegant and productive solution to the problem. Obviously solutions do exist today: raw ADO.NET, , the DAAB, nHibernate, Paul Wilson’s ORM mapper, LLBLgen and more. Many people use these various technologies behind CSLA .NET, and that’s awesome.

So looking forward, I see a bright future. One where the DataPortal_XYZ methods either directly make use of ADO.NET EF and LINQ, or call a data access layer (DAL) that makes use of those technologies to build and return entity objects.

Either way, you can envision this future where the DP_XYZ methods primarily interact with entity objects, deferring all the actual persistence work off to EF/LINQ code. If Microsoft lives up to the promise with EF and LINQ, this model should seriously reduce the complexity of data access, resulting in more developer productivity – giving us more time to focus on the important stuff: object-oriented design ;) .

Lots of developers work very hard to Unit test CSLA BO.

Most of Rocky’s developers don’t like TDD and DDD, more DDD/Alt.Net geeks look down at CSLA either.

Detail instructions are on ScottGu’s blog. Honestly, Linq to SQL’s GUI is much easier to use for NTier dummies, I was surprised by its Stored Procedure support, just by drag and drop, then through ‘configure behavvior…’->’customize’, all the parameters of stored procedure are shown in the list! The amazing part is, for update sp, the original values are included.

Cool! Easy, and the data reading is very fast. (I know I haven’t optimize my NHibernate code very well. ) Now my only concern is, if Linq to SQL always generates DAL and Entities together, then is it possible to unit test entity object only?

One bug in Linq to SQL I found so far, right click menu, view code, I got an error message says:

The name “MyProjectName.MyModuleName” is not a valid identifier. Please choose a different name.

I had to change project name to MyProjectName_MyModuleName to avoid this error. How come Microsoft doesn’t link dot appear in project name?

Another trick is, our stored procedure need developer passing user login for audit purpose. In Linq to Sql Gui view, only class property can be inserted as sp’s parameter. So I added an extra property called UserLogin into my model/table, then delete the auto gen code in XXX.designer.cs, add following lines to partial class:

public partial class MyClass
{

public string UserLogin
{
get
{
return Environment.UserDomainName + “\\” + Environment.UserName;
//or return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
}

}

But the piece of code might be override by dbml regenerate. Instead, I moved those code into a BaseTable class, then change the entity class inherited from this BaseTable. Afterwards, I can change the UpdateEntity method in desinger.cs file, replace the original default(string) to obj.UserLogin. This method won’t be overrode by auto-gen that often. I wish Linq designer can take non-column properties in the future.

There are 2 surprises, SP doesn’t need to change ‘set nocount off‘ and revise datediff which I had to do when using NHiberate.