Created
January 6, 2012 10:17
-
-
Save NOtherDev/1569982 to your computer and use it in GitHub Desktop.
NHibernate mapping-by-code naming convention resembling Fluent's
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NHibernate mapping-by-code naming convention resembling Fluent's | |
// See the blog post: http://notherdev.blogspot.com/2012/01/mapping-by-code-naming-convention.html | |
public class ModelMapperWithNamingConventions : ConventionModelMapper | |
{ | |
public const string ForeignKeyColumnPostfix = "_id"; | |
public const string ManyToManyIntermediateTableInfix = "To"; | |
public const char ElementColumnTrimmedPluralPostfix = 's'; | |
private readonly List<MemberInfo> _ignoredMembers = new List<MemberInfo>(); | |
public ModelMapperWithNamingConventions() | |
{ | |
BeforeMapManyToOne += (inspector, member, customizer) => | |
customizer.Column(member.LocalMember.Name + ForeignKeyColumnPostfix); | |
BeforeMapManyToMany += (inspector, member, customizer) => | |
customizer.Column(member.CollectionElementType().Name + ForeignKeyColumnPostfix); | |
BeforeMapElement += (inspector, member, customizer) => | |
customizer.Column(member.LocalMember.Name.TrimEnd(ElementColumnTrimmedPluralPostfix)); | |
BeforeMapJoinedSubclass += (inspector, type, customizer) => | |
customizer.Key(k => k.Column(type.BaseType.Name + ForeignKeyColumnPostfix)); | |
BeforeMapSet += BeforeMappingCollectionConvention; | |
BeforeMapBag += BeforeMappingCollectionConvention; | |
BeforeMapList += BeforeMappingCollectionConvention; | |
BeforeMapIdBag += BeforeMappingCollectionConvention; | |
BeforeMapMap += BeforeMappingCollectionConvention; | |
BeforeMapComponent += DisableComponentParentAutomapping; | |
IsPersistentProperty((m, d) => !_ignoredMembers.Contains(m)); | |
} | |
private void DisableComponentParentAutomapping(IModelInspector inspector, PropertyPath member, IComponentAttributesMapper customizer) | |
{ | |
var parentMapping = member.LocalMember.GetPropertyOrFieldType().GetFirstPropertyOfType(member.Owner()); | |
DisableAutomappingFor(parentMapping); | |
} | |
private void DisableAutomappingFor(MemberInfo member) | |
{ | |
if (member != null) | |
_ignoredMembers.Add(member); | |
} | |
private void BeforeMappingCollectionConvention(IModelInspector inspector, PropertyPath member, ICollectionPropertiesMapper customizer) | |
{ | |
if (inspector.IsManyToMany(member.LocalMember)) | |
customizer.Table(member.ManyToManyIntermediateTableName()); | |
customizer.Key(k => k.Column(DetermineKeyColumnName(inspector, member))); | |
} | |
private static string DetermineKeyColumnName(IModelInspector inspector, PropertyPath member) | |
{ | |
var otherSideProperty = member.OneToManyOtherSideProperty(); | |
if (inspector.IsOneToMany(member.LocalMember) && otherSideProperty != null) | |
return otherSideProperty.Name + ForeignKeyColumnPostfix; | |
return member.Owner().Name + ForeignKeyColumnPostfix; | |
} | |
} | |
public static class PropertyPathExtensions | |
{ | |
public static Type Owner(this PropertyPath member) | |
{ | |
return member.GetRootMember().DeclaringType; | |
} | |
public static Type CollectionElementType(this PropertyPath member) | |
{ | |
return member.LocalMember.GetPropertyOrFieldType().DetermineCollectionElementOrDictionaryValueType(); | |
} | |
public static MemberInfo OneToManyOtherSideProperty(this PropertyPath member) | |
{ | |
return member.CollectionElementType().GetFirstPropertyOfType(member.Owner()); | |
} | |
public static string ManyToManyIntermediateTableName(this PropertyPath member) | |
{ | |
return String.Join( | |
ModelMapperWithNamingConventions.ManyToManyIntermediateTableInfix, | |
member.ManyToManySidesNames().OrderBy(x => x) | |
); | |
} | |
private static IEnumerable<string> ManyToManySidesNames(this PropertyPath member) | |
{ | |
yield return member.Owner().Name; | |
yield return member.CollectionElementType().Name; | |
} | |
} |
Components are handled by BeforeMapComponent
. This is for elements, single-column value types collections mapped with Element
mapping. See here: http://notherdev.blogspot.com/2012/01/mapping-by-code-onetomany-and-other.html for some clues how it differ to components (multi-column value types).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@NOtherDev That was my initial guess too, but from testing NHibernate didn't do that. (Tested with a collection of strings on a parent element mapped as
Component()
.) Unless I'm testing too hastily and didn't check thorougly enough that is. (Thanks for coming back so quickly!)