database column to constant value without the need for a property in the entity class with mapping by code
Asked Answered
S

2

1

this is almost the same as this question except using NH's mapping-by-code.

I really need the virtual properties because i also want to use SchemaExport to create the database for different rdbms without the need to create/maintain scripts for each.

Maybe there is a MbC Guru who knows how to do it with MbC

Update: the obvious simple code

Property("dummyProperty", c =>
{
    c.Column("legacyColumn");
    c.Access(typeof(MyPropertyAccessor));
});

does not work

NHibernate.MappingException: Unable to instantiate mapping class (see InnerException): Test.MbC.GroupMap ---> System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> NHibernate.MappingException: Member not found. The member 'dummyProperty' does not exists in type Test.Data.Group
   bei NHibernate.Mapping.ByCode.Impl.CustomizersImpl.PropertyContainerCustomizer`1.GetPropertyOrFieldMatchingNameOrThrow(String memberName)
   bei NHibernate.Mapping.ByCode.Impl.CustomizersImpl.PropertyContainerCustomizer`1.RegisterNoVisiblePropertyMapping(String notVisiblePropertyOrFieldName, Action`1 mapping)
   bei 
   ...

neither does this, because god knows why MbC checks internally with reflection, that the property does exist on the class.

var parameter = Expression.Parameter(typeof(T), "x");
Expression body = Expression.Property(parameter, new GetterPropertyInfo(typeof(T), defaultgetter));
body = Expression.Convert(body, typeof(object));

var lambda = Expression.Lambda<Func<T, object>>(body, parameter);

Property(lambda, m =>
{
    m.Column(defaultgetter.PropertyName);
    m.Access(propertyAccessorType);
});

and even disabling the test with reflection through overriding RegisterProperty() in ClassMapping it still throws while building the hbm complaining:

System.ArgumentOutOfRangeException: Can't add a property of another graph
Parametername: property
   bei NHibernate.Mapping.ByCode.Impl.AbstractBasePropertyContainerMapper.Proper
ty(MemberInfo property, Action`1 mapping)
   bei NHibernate.Mapping.ByCode.ModelMapper.MapProperty(MemberInfo member, Prop
ertyPath propertyPath, IMinimalPlainPropertyContainerMapper propertiesContainer)

   bei NHibernate.Mapping.ByCode.ModelMapper.MapProperties(Type propertiesContai
nerType, IEnumerable`1 propertiesToMap, IPropertyContainerMapper propertiesConta
iner, PropertyPath path)
   bei NHibernate.Mapping.ByCode.ModelMapper.MapProperties(Type propertiesContai
nerType, IEnumerable`1 propertiesToMap, IPropertyContainerMapper propertiesConta
iner)
   bei NHibernate.Mapping.ByCode.ModelMapper.MapRootClass(Type type, HbmMapping
mapping)
   bei NHibernate.Mapping.ByCode.ModelMapper.CompileMappingFor(IEnumerable`1 typ
es)

Mapping by code should be more flexible than FNH? Where?

Swaim answered 7/5, 2012 at 13:21 Comment(2)
no ideas? i just need a starting pointSwaim
MbC seems to remove completely the entity model (ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/…) from NH which was one source of flexibility of NH.Swaim
S
2

After investing a lot of time trying to do this rather simple mapping in MbC i concede and throw aboard MbC again.

Even simple Mapping like this is not remotely possible with the oh so flexible MbC

public class MyClassMap : ClassMap<MyClass>
{
    public MyClassMap()
    {
        Map(x => this.VirtualProp, "legacyColumn").Default("123").Access.None();
    }

    public long VirtualProp { get; set; }
}

the advantage here is that i can use SchemaExport to create a compatible schema for the legacy app without polluting my domain classes

Swaim answered 29/5, 2012 at 13:17 Comment(0)
C
0

You can do it pretty much in the same way as in the linked question. Implementation of PropertyAccessor stays the same. To use it within mapping-by-code, map the column using string overload (the name of the property is required but not really used in this case) and attach the accessor:

Property("dummyPropertyNameForConstant", c =>
{
    c.Column("ConstantColumn");
    c.Access(typeof(CustomAccessor));
});
Caplan answered 9/5, 2012 at 17:24 Comment(5)
thx for the answer but i already tried that. i added it to the questionSwaim
btw your mapping by code series inspired me to try the new mapping by code.Swaim
Seems like mapping-by-code requires a field even if accessor doesn't require it. You can try adding the dummyProperty private field in the entity class as a workaround. It wouldn't be used.Caplan
the workaround renders the whole idea of the propertyaccessor useless and reintroduces the broken window.Swaim
if you ever come across a way to do what what i want feel free to come back share itSwaim

© 2022 - 2024 — McMap. All rights reserved.