I'm building an application which uses NHibernate mapping by code, and I am unable to map protected properties when I use a component mapping (equivalent to hbm composite-element mapping) for a collection of value objects.
I am able to map protected properties in entity and compoment mappings for single value objects, it is just protected properties do not appear to be supported when mapping collections of value objects.
public class MyEntity
{
public virtual int Id { get; protected set; }
protected virtual MyValueObject MyValueObject { get; set; }
}
public class MyValueObject
{
protected string SomeString { get; set; }
protected ISet<NestedValueObject> NestedValueObjects { get; set; }
// Constructor, Equals/GetHashcode overrides, etc.
}
public class NestedValueObject
{
public string Name { get; set; }
protected DateTime CreatedOn { get; set; } // Audit only property
// Constructor, Equals/GetHashcode overrides, etc.
}
public MyEntityMap()
{
Table("MyEntityTable");
Id(x => x.Id, map =>
{
map.Column("Id");
});
Component<MyValueObject>("MyValueObject", c =>
{
// Protected property maps correctly
c.Property("SomeString", map =>
{
map.NotNullable(true);
});
c.Set<NestedValueObject>("NestedValueObjects", map =>
{
map.Table("NestedValueObjectsTable");
map.Key(k => k.Column("MyEntityId"));
}, r => r.Component(n =>
{
// Public property maps correctly
n.Property(x => x.Name);
// Compilation fail - there is no method that supports protected properties in component mappings
n.Property<DateTime>("CreatedOn", map =>
{
map.NotNullable(true);
});
}));
});
}
This is because IMinimalPlainPropertyContainerMapper<TContainer>
supports protected properties, while IComponentElementMapper<TComponent>
doesn't.
Is there a reason for this? It seems reasonable that a value object should be allowed to have protected properties which are for auditing purposes only and do not form a part of its conceptual identity, and protected properties are supported with the component mapping for single value objects.
It looks like this is missing feature, rather than a design decision, and will be fixed in a future release of NHibernate:
https://nhibernate.jira.com/browse/NH-3993
As a workaround until this release, the alternatives would be to make the properties public or to map the value object as an entity with a composite id using a one-to-many mapping, since these support protected variables.