views:

511

answers:

1

I'd like to use Example.Create() to query just by the unique values of an instance. To do so I need to find out the value of the unique-key property that had been set inside the mapping file, like this:

  <property name="MyColumn">
    <column name="MyColumn" unique-key="MyUniqueKeyGroup"/>
  </property>

For better understanding - here is the important part of the code:

criteria.Add(Example.Create(myObject).SetPropertySelector(new MyPropertySelector()));

[...]

public class MyPropertySelector: NHibernate.Criterion.Example.IPropertySelector
{
    #region IPropertySelector Member

    public bool Include(object propertyValue, string propertyName, IType type)
    {
         /*  here is where I want to check if the property belongs 
          *  to the unique-key group 'MyUniqueKeyGroup' and return true if so 
          */
    }

    #endregion
}

What do I need to do, to find out if a property belongs to the unique-key group 'MyUniqueKeyGroup'?

A: 

You'll need to probe the Nhibernate.Cfg.Configuration object to get this. You would have constructed this somewhere in order to create your ISessionFactory instance. Something like this may work:

private NHibernate.Cfg.Configuration _configuration;

[...]

var selector = new MyPropertySelector<MyClass>(_configuration, "MyUniqueKeyGroup");
criteria.Add(Example.Create(myObject)
                    .SetPropertySelector(selector));

[...]

public class MyPropertySelector<T>: NHibernate.Criterion.Example.IPropertySelector
{
    private NHibernate.Cfg.Configuration _onfiguration;
    private IEnumerable<NHibernate.Mapping.Column> _keyColumns;

    public MyPropertySelector(NHibernate.Cfg.Configuration cfg, string keyName)
    {
        _configuration = cfg;
        _keyColumns = _configuration.GetClassMapping(typeof(T))
                                .Table
                                .UniqueKeyIterator
                                .First(key => key.Name == keyName)
                                .ColumnIterator);

    }

    public bool Include(object propertyValue, string propertyName, IType type)
    {
         return _configuration.GetClassMapping(typeof(T))
                          .Properties
                          .First(prop => prop.Name == propertyName)
                          .ColumnIterator
                              .Where(col => !col.IsFormula)
                              .Cast<NHibernate.Mapping.Column>()
                              .Any(col => _keyColumns.Contains(col)))
    }
}

I haven't actually compiled this to check it works, so YMMV. And it could certainly be made more efficient! It also doesn't do any trapping of error conditions (e.g. if you give it an incorrect key name, or an unmapped class type then it will crash).

Cheers, John

John Rayner
Thank you! Using the NHibernate.Cfg.Configuration had been the hint I needed. I originally thought that I could solve this using the SessionFactory.GetClassMetadata() function.
Martin