Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

NHibernate Metadata

I know that O/RMs like NHibernate are supposed to shield us from the gory database internals such as tables, views, columns and such; however, at times, I do have the need to know how my domain model translates to the database. NHibernate, of course, provides us with the information we need, but it isn’t always easy to find, so I wrote my own extension methods for ISessionFactory that allow me to get the metadata I need in an easy way:

   1: public static IEnumerable<PropertyInfo> GetComponents(this ISessionFactory sessionFactory, Type entityType)
   2: {
   3:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
   4:     IClassMetadata metadata = sessionFactory.GetClassMetadata(entityName);
   5:  
   6:     for (Int32 i = 0; i < metadata.PropertyTypes.Length; ++i)
   7:     {
   8:         IType property = metadata.PropertyTypes[i];
   9:  
  10:         if (property is ComponentType)
  11:         {
  12:             String propertyName = metadata.PropertyNames[i];
  13:             yield return (entityType.GetProperty(propertyName));
  14:         }
  15:     }
  16: }
  17:  
  18: public static IEnumerable<PropertyInfo> GetUserTypes(this ISessionFactory sessionFactory, Type entityType)
  19: {
  20:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
  21:     IClassMetadata metadata = sessionFactory.GetClassMetadata(entityName);
  22:  
  23:     for (Int32 i = 0; i < metadata.PropertyTypes.Length; ++i)
  24:     {
  25:         IType property = metadata.PropertyTypes[i];
  26:  
  27:         if (property is CustomType)
  28:         {
  29:             String propertyName = metadata.PropertyNames[i];
  30:             yield return (entityType.GetProperty(propertyName));
  31:         }
  32:     }
  33: }
  34:  
  35: public static IEnumerable<PropertyInfo> GetProperties(this ISessionFactory sessionFactory, Type entityType)
  36: {
  37:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
  38:     IClassMetadata metadata = sessionFactory.GetClassMetadata(entityName);
  39:     
  40:     for (Int32 i = 0; i < metadata.PropertyTypes.Length; ++i)
  41:     {
  42:         IType property = metadata.PropertyTypes[i];
  43:  
  44:         if (!(property is OneToOneType) && !(property is ManyToOneType) && !(property is ComponentType))
  45:         {
  46:             String propertyName = metadata.PropertyNames[i];
  47:             yield return (entityType.GetProperty(propertyName));                    
  48:         }
  49:     }
  50: }
  51:  
  52: public static IEnumerable<PropertyInfo> GetAssociations(this ISessionFactory sessionFactory, Type entityType)
  53: {
  54:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
  55:     IClassMetadata metadata = sessionFactory.GetClassMetadata(entityName);
  56:  
  57:     for (Int32 i = 0; i < metadata.PropertyTypes.Length; ++i)
  58:     {
  59:         IType property = metadata.PropertyTypes[i];
  60:  
  61:         if (property is OneToOneType)
  62:         {
  63:             String propertyName = metadata.PropertyNames[i];
  64:             yield return (entityType.GetProperty(propertyName));
  65:         }
  66:         else if (property is ManyToOneType)
  67:         {
  68:             String propertyName = metadata.PropertyNames[i];
  69:             yield return (entityType.GetProperty(propertyName));
  70:         }
  71:     }
  72: }
  73:  
  74: public static PropertyInfo GetIdentifier(this ISessionFactory sessionFactory, Type entityType)
  75: {
  76:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
  77:     AbstractEntityPersister persister = (sessionFactory as ISessionFactoryImplementor).TryGetEntityPersister(entityName) as AbstractEntityPersister;
  78:  
  79:     if (persister != null)
  80:     {
  81:         return (entityType.GetProperty(persister.IdentifierPropertyName));
  82:     }
  83:     else
  84:     {
  85:         return (null);
  86:     }
  87: }
  88:  
  89: public static IEnumerable<String> GetIdentifierColumnNames(this ISessionFactory sessionFactory, Type entityType)
  90: {
  91:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
  92:     AbstractEntityPersister persister = (sessionFactory as ISessionFactoryImplementor).TryGetEntityPersister(entityName) as AbstractEntityPersister;
  93:  
  94:     if (persister != null)
  95:     {
  96:         return (persister.IdentifierColumnNames);
  97:     }
  98:     else
  99:     {
 100:         return (null);
 101:     }
 102: }
 103:  
 104: public static String GetColumnName(this ISessionFactory sessionFactory, Type entityType, String propertyName)
 105: {
 106:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
 107:     AbstractEntityPersister persister = (sessionFactory as ISessionFactoryImplementor).TryGetEntityPersister(entityName) as AbstractEntityPersister;
 108:  
 109:     if (persister != null)
 110:     {
 111:         return (persister.GetPropertyColumnNames(propertyName).SingleOrDefault());
 112:     }
 113:     else
 114:     {
 115:         return (null);
 116:     }
 117: }
 118:  
 119: public static String GetTableName(this ISessionFactory sessionFactory, Type entityType)
 120: {
 121:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
 122:     AbstractEntityPersister persister = (sessionFactory as ISessionFactoryImplementor).TryGetEntityPersister(entityName) as AbstractEntityPersister;
 123:  
 124:     if (persister != null)
 125:     {
 126:         return (persister.TableName);
 127:     }
 128:     else
 129:     {
 130:         return (null);
 131:     }
 132: }
 133:  
 134: public static IEnumerable<PropertyInfo> GetCollections(this ISessionFactory sessionFactory, Type entityType)
 135: {
 136:     String entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType);
 137:     IClassMetadata metadata = sessionFactory.GetClassMetadata(entityName);
 138:     String prefix = String.Concat(entityName, ".");
 139:     IDictionary<String, ICollectionMetadata> collectionMetadata = sessionFactory.GetAllCollectionMetadata().Where(x => x.Key.StartsWith(prefix)).ToDictionary(x => x.Key, x => x.Value);
 140:  
 141:     foreach (String key in collectionMetadata.Keys)
 142:     {
 143:         String propertyName = key.Replace(prefix, String.Empty);
 144:         yield return(entityType.GetProperty(propertyName));
 145:     }
 146: }

A brief explanation:

  • GetProperties: all the mapped properties for a given entity;
  • GetComponents: given an entity type, returns all the properties that are mapped as components;
  • GetUserTypes: all the properties that are mapped as custom user types;
  • GetIdentifier: the property that is mapped as the identifier;
  • GetAssociations: properties mapped as one to one or many to one, that is, that point to another entity;
  • GetCollections: properties mapped as one to many, that is, collections, of any type;
  • GetTableName: the table or view name where the entity is stored;
  • GetIdentifierColumnNames: the names of the column(s) that compose the primary key for the table;
  • GetColumnName: the table or view column that store a given property.

Comments

Ricardo Peres said:

@Phil:

That is up to you! :-)

If you never had that need, fine... I did, for writing direct SQL for reporting purposes.

You may find more useful knowing dynamically the mapped properties, collections and associations, I myself use that more often.

# February 2, 2012 12:38 PM

Cheap Van Halen Tickets said:

Content management with DataObjects.Net follows the domain-driven design idea.

# February 2, 2012 11:13 PM

Προσφορες Ξενοδοχειων said:

Thanks Ricardo, I agree with you!!

# July 6, 2012 12:47 PM