I've been slowly replacing our NHibernate XML mapping files with
ClassMap and ran into a minor snag with our composite key classes.
Unfortunately we are supporting a legacy database that uses some evil
and nasty composite keys... I hate 'em but we can't change the schema.
To solve this problem, I created the CompositeComponentId with the
CompositeComponentPart class to support mapping composite-id to a
class. The CompositeComponentId works similarly to Component:

CompositeComponentId<IdentityClass>(x => x.Property, m =>
{
        m.WithKeyProperty(x => x.Property, "FieldName");
        m.WithKeyReference(x => x.Property, "FieldName");
});

Keep in mind this code is a sideline addition created by me and I do
not guarantee it will meet your needs or that it will work for you.
This is a temporarily solution I created to meet my immediate needs so
feel free to use it at your own risk. I elected this approach because
it minimizes the changes to the existing code base (e.g. adds one
method to ClassMapBase and adds one class to the Mapping folder).

All that's needed it to add CompositeComponentId to ClassMapBase:

public virtual CompositeComponentPart<C> CompositeComponentId<C>
(Expression<Func<T, object>> expression,
Action<CompositeComponentPart<C>> action)
{
        PropertyInfo property = ReflectionHelper.GetProperty(expression);
        CompositeComponentPart<C> part = new CompositeComponentPart<C>
(property);
        AddPart(part);
        action(part);
        return part;
}

and add the CompositeComponentPart class:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Xml;

namespace FluentNHibernate.Mapping
{
        public class CompositeComponentPart<T> : IMappingPart,
IAccessStrategy<CompositeComponentPart<T>>
        {
                private readonly 
AccessStrategyBuilder<CompositeComponentPart<T>>
_access;
                private readonly IList<KeyProperty> _keyProperties;
                private readonly PropertyInfo _property;

                public CompositeComponentPart(PropertyInfo property)
                {
                        _property = property;
                        _keyProperties = new List<KeyProperty>();
                        _access = new 
AccessStrategyBuilder<CompositeComponentPart<T>>
(this);
                }

                public void SetAttribute(string name, string value)
                {
                        throw new NotImplementedException();
                }

                public void SetAttributes(Attributes atts)
                {
                        foreach(var key in atts.Keys)
                        {
                                SetAttribute(key, atts[key]);
                        }
                }

                public void Write(XmlElement classElement, IMappingVisitor 
visitor)
                {
                        XmlElement element = 
classElement.AddElement("composite-id")
                                .WithAtt("class", 
_property.PropertyType.FullName)
                                .WithAtt("name", _property.Name);

                        foreach(var keyProp in _keyProperties)
                        {
                                keyProp.Write(element, visitor);
                        }
                }

                public int Level
                {
                        get { return 1; }
                }

                public PartPosition Position
                {
                        get { return PartPosition.First; }
                }

                /// <summary>
                /// Defines a property to be used as a key for this 
composite-id.
                /// </summary>
                /// <param name="expression">A member access lambda expression 
for
the property</param>
                /// <returns>The composite identity part fluent 
interface</returns>
                public CompositeComponentPart<T> 
WithKeyProperty(Expression<Func<T,
object>> expression)
                {
                        return WithKeyProperty(expression, null);
                }

                /// <summary>
                /// Defines a property to be used as a key for this composite-id
with an explicit column name.
                /// </summary>
                /// <param name="expression">A member access lambda expression 
for
the property</param>
                /// <param name="columnName">The column name in the database to 
use
for this key, or null to use the property name</param>
                /// <returns>The composite identity part fluent 
interface</returns>
                public CompositeComponentPart<T> 
WithKeyProperty(Expression<Func<T,
object>> expression, string columnName)
                {
                        var prop = ReflectionHelper.GetProperty(expression);

                        var keyProperty = new KeyProperty(prop, false)
                        {
                                ColumnName = columnName
                        };

                        _keyProperties.Add(keyProperty);
                        return this;
                }

                /// <summary>
                /// Defines a reference to be used as a many-to-one key for this
composite-id with an explicit column name.
                /// </summary>
                /// <param name="expression">A member access lambda expression 
for
the property</param>
                /// <returns>The composite identity part fluent 
interface</returns>
                public CompositeComponentPart<T> 
WithKeyReference(Expression<Func<T,
object>> expression)
                {
                        return WithKeyReference(expression, null);
                }

                /// <summary>
                /// Defines a reference to be used as a many-to-one key for this
composite-id with an explicit column name.
                /// </summary>
                /// <param name="expression">A member access lambda expression 
for
the property</param>
                /// <param name="columnName">The column name in the database to 
use
for this key, or null to use the property name</param>
                /// <returns>The composite identity part fluent 
interface</returns>
                public CompositeComponentPart<T> 
WithKeyReference(Expression<Func<T,
object>> expression, string columnName)
                {
                        var property = ReflectionHelper.GetProperty(expression);

                        var keyProperty = new KeyProperty(property, true)
                        {
                                ColumnName = columnName
                        };

                        _keyProperties.Add(keyProperty);
                        return this;
                }

                /// <summary>
                /// Set the access and naming strategy for this identity.
                /// </summary>
                public AccessStrategyBuilder<CompositeComponentPart<T>> Access
                {
                        get { return _access; }
                }
        }
}

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Fluent NHibernate" group.
To post to this group, send email to fluent-nhibernate@googlegroups.com
To unsubscribe from this group, send email to 
fluent-nhibernate+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/fluent-nhibernate?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to