составной ключ и наследование - PullRequest
2 голосов
/ 14 октября 2011

у меня есть следующие классы и сопоставления

abstract class BaseClass
{
    public virtual int Keypart1 { get; set; }
    public virtual int Keypart2 { get; set; }

    // overridden Equals() and GetHashCode()
}

class InheritingClass : BaseClass
{
}

class BaseClassMap : ClassMap<BaseClass>
{
    public BaseClassMap()
    {
        CompositeId()
            .KeyProperty(x => x.Keypart1)
            .KeyProperty(x => x.Keypart2);
    }
}

class InheritingClassMap : SubclassMap<InheritingClass>
{
    public InheritingClassMap()
    {
        KeyColumn("Keypart1");
        KeyColumn("Keypart2");
    }
}

вставка, обновление и session.Get () работает нормально, но запрашивает как

var result = session.CreateCriteria<InheritingClass>().List<InheritingClass>();

бросает

NHibernate.InstantiationException: Cannot instantiate abstract class or interface: ConsoleApplication1.BaseClass
   bei NHibernate.Tuple.PocoInstantiator.Instantiate()
   bei NHibernate.Tuple.Component.AbstractComponentTuplizer.Instantiate()
   bei NHibernate.Type.ComponentType.Instantiate(EntityMode entityMode)
   bei NHibernate.Type.ComponentType.Instantiate(Object parent, ISessionImplementor session)
   bei NHibernate.Type.EmbeddedComponentType.Instantiate(Object parent, ISessionImplementor session)
   bei NHibernate.Type.ComponentType.ResolveIdentifier(Object value, ISessionImplementor session, Object owner)
   bei NHibernate.Type.ComponentType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner)
   bei NHibernate.Loader.Loader.GetKeyFromResultSet(Int32 i, IEntityPersister persister, Object id, IDataReader rs, ISessionImplementor session)
   bei NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies)
...

кажется, что NH пытается создать абстрактный базовый класс как составной ключ и терпит неудачу. Могу ли я как-то обойти это?

ОБНОВЛЕНИЕ: мой тестовый код

var config = Fluently.Configure()
    .Database(SQLiteConfiguration.Standard.InMemory().ShowSql().FormatSql())
    .Mappings(m => m.FluentMappings
        .Add<BaseClassMap>()
        .Add<InheritingClassMap>()
    )
    .BuildConfiguration();

var sf = config.BuildSessionFactory();

using (var session = sf.OpenSession())
{
    new SchemaExport(config).Execute(false, true, false, session.Connection, null);

    var obj = new InheritingClass
    {
        Keypart1 = 1,
        Keypart2 = 2,
    };

    session.Save(obj);
    session.Flush();
    session.Clear();

    // throws here
    var result = session.CreateCriteria<InheritingClass>().List<InheritingClass>();
}

Ответы [ 2 ]

2 голосов
/ 17 октября 2011

Как выглядит ваша база данных?Согласно вашему отображению вы используете отображение таблицы на подкласс.В этом случае NHibernate попытается создать экземпляр BaseClass, если в таблице InheritingClass.

edit не найдена строка: существует атрибут abstract="true" для <class> в отображении NHibernate.что может решить вашу проблему.Но, похоже, это не отображается в Fluent NHibernate для ClassMap, только для SubclassMap (что вам не поможет).

Но, возможно, вы также можете решить проблему с помощью компонентадля составного идентификатора (так что NHibernate не нужно создавать объект BaseClass для его EntityKey. См. здесь для получения информации об этом.

0 голосов
/ 19 октября 2011

спасибо за крем это то, что я получаю в итоге

abstract class BaseClass
{
    public virtual BaseClassId Key { get; set; }
}

class BaseClassId
{
    public virtual int Keypart1 { get; set; }
    public virtual int Keypart2 { get; set; }

    public override bool Equals(object obj)
    {
        var other = obj as BaseClassId;
        return (other != null) && (Keypart1 == other.Keypart1) && (Keypart2 == other.Keypart2);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return Keypart1 + Keypart2;
        }
    }
}

// mapping
CompositeId(b => b.Key)
    .KeyProperty(x => x.Keypart1)
    .KeyProperty(x => x.Keypart2);


var obj = new InheritingClass
{
    Key = new BaseClassId
    {
        Keypart1 = 1,
        Keypart2 = 2,
    }
};
...