Question

I've got a class with a bunch of [ColumnName("foo")] NHibernate attributes. Is there an easy way to ask NHibernate to list all of the ColumnNames for a given class?

It sounds like it should be really easy but I'm just not seeing any kind of inspection in the NHibernate docs (or maybe I'm just blind today).

Was it helpful?

Solution

Use LINQ and reflection:

var columns = typeof(TheClass).GetProperties()
    .Where(property => property.GetCustomAttributes(typeof(ColumnNameAttribute), false).Count > 0)
    .Select(property => property.Name);

OTHER TIPS

I had this same problem, but found IClassMetadata doesn't have any column information, just property types, names, identifier, and table information.

What worked for me:

PersistentClass persistentClass = cfg.GetClassMapping(typeof(MyEntity));
Property property = persistentClass.GetProperty(propertyName);
property.ColumnIterator   // <-- the column(s) for the property

How to get the database column names for an entity mapped by NHibernate:

using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Persister.Entity;

namespace Stackoverflow.Example
{
    /// <summary>
    /// NHibernate helper class
    /// </summary>
    /// <remarks>
    /// Assumes you are using NHibernate version 3.1.0.4000 or greater (Not tested on previous versions)
    /// </remarks>
    public class NHibernateHelper
    {
        /// <summary>
        /// Gets the list of database column names for an entity
        /// </summary>
        /// <param name="sessionFactory">NHibernate SessionFactory</param>
        /// <param name="entity">A mapped entity</param>
        /// <returns>List of column names</returns>
        public static IEnumerable<string> GetPropertyColumnNames(ISessionFactory sessionFactory, object entity)
        {
            Type entityType = entity == null ? null : entity.GetType();

            List<string> columnNameList = null;

            // This has some cool methods and properties so check it out
            var metaData = entityType == null ? null : sessionFactory.GetClassMetadata(entityType.ToString());

            //- metaData validity check ... will be null if provided type is not mapped
            if (metaData != null)
            {
                // This has some even cooler methods and properties so definitely check this out
                var entityPersister = (AbstractEntityPersister) metaData;

                //- how to get the entity's identifier
                //- string entityIdentifier = metaData.IdentifierPropertyName;

                //- Get the database identifier
                //- can have multiple in case of composite keys
                IEnumerable<string> dbIdentifierNameList = entityPersister.KeyColumnNames;

                var propertyNameList = entityPersister.PropertyNames;

                // Adding the database identifier first
                columnNameList = new List<string>(dbIdentifierNameList);
                //- then add properties column names
                foreach (var propertyName in propertyNameList)
                {
                    var columnNameArray = entityPersister.GetPropertyColumnNames(propertyName);
                    columnNameList.AddRange(columnNameArray.Where(columnName => dbIdentifierNameList.Contains(columnName) == false));
                }
            }

            return columnNameList;
        }
    }
}   

Usage:

// Get your NHiberate SessionFactory wherever that is in your application
var sessionFactory = NHibernateHelper.SessionFactory;

// Get an entity that you know is mapped by NHibernate
var customer = new Customer();

// Get a list of the database column names for the entity
var columnNames = 
        Stackoverflow.Example.NHibernateHelper.GetPropertyColumnNames( sessionFactory, customer );

Bask in the glory of this awesomeness :)

Use NHibernate's Metadata

// get an instance to the metadata 
IClassMetadata metadata = sessionfactory.GetClassMetadata(typeof(MyEntity));

// use properties and methods from the metadata:
// metadata.PropertyNames
// metadata.PropertyTypes
// metadata.GetIdentifier()
// and more

// or get the metadata for all classes at once
IDictionary allClassMetaData = factory.GetAllClassMetadata();
metadata = allClassMetaData[typeof(MyEntity)];

You get what NHibernate actually knows, independent of how it is defined; using attributes, xml mappings or FluentNHibernate. This makes it more stable and more reliable than using reflection on your own.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top