tags:

views:

58

answers:

2

In our SOA application we have several customers' data in the same database and in the same tables.

To control access, we have a column that describes this relationship. This column isn't represented in the domain model, however. I know about query only properties - so, for querying - it is working perfectly.

However, how do I write to this column when saving new rows/entities?

Code:

public class Customer
{
    public virtual long Id{get;private set;}
    public virtual string AccountNumber{get;set;}
}

Mapping:

<class Name="Customer">
  <id name="Id">
    <generator class="native"/>
  </id>
  <property name="AccountNumber"/>
  <property name="Partition" access="noop" not-null="true"/>
</class>
+1  A: 

Is there a problem including the Partition property as part of the domain?

Personally I would add it as part of the domain model and save yourself a whole lot of pain. The very limited view that we have of the problem is that it appears that you would benifit from the Partion property being a part of the domain either as part of the customer object or refactored to a superclass of customer.

Having said that if it must stay the way it is, look at implementing either IPreInsertEventListner / IPreUpdateEventListener or the IPostInsertEventListener / IPostUpdateEventListener You could check for the Customer class and execute a SQL query that updates the Partition column in the database. It appears that most people use these event handlers for audit logging, but they should still be applicable for this situation.

Ayende's Blog - NHibernate IPreUpdateEventListener & IPreInsertEventListener

Nathan Fisher
The problem with having the Partition property is that it pollutes the domain - it is a persistence concern only. The IPreUpdateEventListener and IPreInsertEventListener does not work in this context as the property Partition is _not_ a property of the entity. (If I understand it correctly from Ayende's post, it is only possible to change actual properties of the entity).
Goblin
+1  A: 

I'm not sure to understand from where the value that should be inserted will come from if not set when creating entities (assuming they would provide the appropriate attribute of course) but...

One option would be to use an IInterceptor to alter the SQL during OnPrepareStatement and add whatever you want in case of INSERT.

using System;
using System.Collections;
using NHibernate.SqlCommand;
using NHibernate.Type;

namespace NHibernate
{
    [Serializable]
    public class MyInterceptor : IInterceptor
    {
        ...

        public SqlString OnPrepareStatement(SqlString sql)
        {
            ///Do what is required here to alter the SQL string
            return sql;
        }
    }
}

And apply your interceptor either at the session level or globally.

Reference

Pascal Thivent
The value will come from the security-framework as it is part of the login-procedure. The IInterceptor looks promising - I'll take a look at it :-).
Goblin
@Goblin Ah, I see. This option should work then.
Pascal Thivent
I got it working! Thanks a bunch!
Goblin
@Goblin You're welcome!
Pascal Thivent