开发者

composite Key and inheritance

开发者 https://www.devze.com 2023-04-12 21:15 出处:网络
i have the following classes and mappings abstract class BaseClass { public virtual int Keypart1 { get; set; }

i have the following classes and mappings

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");
    }
}

inserting, updating and session.Get() work fine but querying like

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

throws

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)
...

it seems NH tries to instantiate the abstract baseclass as a compositekey and fails. Can i somehow work around that?

UPDATE: my testcode

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, nul开发者_运维技巧l);

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

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

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


How does your database look like? According to your mapping, you are using a table-per-subclass mapping. In this case NHibernate will try to create an instance of BaseClass if no row is found in the table of InheritingClass.

edit: There is a abstract="true" attribute for a <class> in NHibernate mapping which might fix your problem. But it seems like this isn't exposed in Fluent NHibernate for a ClassMap, only for SubclassMap (which won't help you).

But maybe you could also fix the problem by using a component for the composite ID (so that NHibernate doesn't need to create a BaseClass object for its EntityKey. See here for infos about that.


thx to cremor this is what i end up with

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,
    }
};
0

精彩评论

暂无评论...
验证码 换一张
取 消