使用NHibernate的子类;获取NHibernate.WrongClassException(有时)

时间:2012-12-12 08:25:55

标签: c# nhibernate nhibernate-mapping

WinForms应用程序,NHibernate v3.3.x,.Net 4,Windows 7(32位),Oracle 10g后端

我们正在使用带有AuditTrail表的遗留数据库,其中列操作类型(AKTIONSCODE)控制其他(可选)参数的含义(Para1-Para4)

我创建了一个相应的班级AuditTrail;  和AuditTrailAsmRuleSetStateAuditTrailTestSpecSetState之类的派生子类,唯一的目的是为公共参数获取一些不错的getter和setter。

插入条目工作正常。

阅读AuditTrailAsmRuleSetState条目和其他派生类也正常工作。

但有时我会得到一个NHibernate.WrongClassException,读取AuditTrailTestSpecSetState条目; 关闭应用程序(可能关闭会话?)并再次阅读相同的条目将再次工作!?

非常感谢您的建议。

AuditTrail表和nHibernate映射文件如下所示:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MeCIS_DAL"
    namespace="Com.XY.App.DAL.Entities" >
<class name="AuditTrail" 
     table="AUDITTRAIL"  schema="MECIS_OWNER"
     dynamic-update="true" dynamic-insert="true" rowid="rowid">
<id name="AID" column="AID" unsaved-value="0">
  <generator class="native">
    <param name="sequence">mecis_owner.seq_audittrail</param>
  </generator>
</id>
<discriminator formula="case when aktionscode=20005 then '1' 
when aktionscode=20010 then '2' 
when aktionscode=20020 then '3' 
else '10' end" />

<property name="AuditTime" column="DATUM" not-null="true" />
<many-to-one name="User" class="Bearbeiter"
             fetch="join" cascade="none" not-null="true" >
  <column name="BEARBEITER_ID" />
</many-to-one>
<property name="HostName" column="RECHNER" length="15" />
<many-to-one name="AuditTrailDefObj" class="AuditTrailDef"
             fetch="join" cascade="none" not-null="true" >
  <column name="AKTIONSCODE" />
</many-to-one>
<property name="Para1" column="PARAMETER1" length="40" />
<property name="Para2" column="PARAMETER2" length="40" />
<property name="Para3" column="PARAMETER3" length="40" />
<property name="Para4" column="PARAMETER4" length="250" />

<subclass name="AuditTrailAsmRuleSetState" discriminator-value="1" entity-name="SetStateAsmRule">
  <!-- subclass specific properties -->
</subclass>

<subclass name="AuditTrailTestSpecObjSetState" discriminator-value="2" entity-name="SetStateTestSpecObj">
  <!-- subclass specific properties -->
</subclass>

<subclass name="AuditTrailTestSpecSetState" discriminator-value="3" entity-name="SetStateTestSpec">
  <!-- subclass specific properties -->
</subclass>

<subclass name="AuditTrail" discriminator-value="10" entity-name="BaseStd">
  <!-- subclass specific properties -->
</subclass>

      </class>
  <!--
 TABLE AUDITTRAIL
 Name                                      Null?    Type                        
 ===================================================================
 AID                                       NOT NULL NUMBER(11)
 DATUM                                     NOT NULL DATE
 BEARBEITER_ID                             NOT NULL NUMBER(5)
 RECHNER                                            VARCHAR2(15)
 AKTIONSCODE                               NOT NULL NUMBER(5)
 PARAMETER1                                         VARCHAR2(40)
 PARAMETER2                                         VARCHAR2(40)
 PARAMETER3                                         VARCHAR2(40)
 PARAMETER4                                         VARCHAR2(250)             
  -->
</hibernate-mapping>

类AuditTrail和派生类AuditTrailTestSpecSetState如下所示: (派生类AuditTrailTestSpecObjSetStateAuditTrailAsmRuleSetStateAuditTrailTestSpecSetState

非常相似
public class AuditTrail : EntityBase
{
..constants, remarks, etc. omitted

    public AuditTrail(AuditTrailType type)
    {
        this.Init();
        this.SetAuditTrailType(type);
    }

    public AuditTrail(AuditTrailType type, string para1 = null, string para2 = null, string para3 = null, string para4 = null)
    {
        this.Init();
        this.SetAuditTrailType(type);
        this.Para1 = StringHelper.Truncate(para1, this.para1MaxLength);
        this.Para2 = StringHelper.Truncate(para2, this.para2MaxLength);
        this.Para3 = StringHelper.Truncate(para3, this.para3MaxLength);
        this.Para4 = StringHelper.Truncate(para4, this.para4MaxLength);
    }

    public AuditTrail(AuditTrailType type, params string[] parameters)
    {
        this.Init();
        this.SetAuditTrailType(type);

        if (parameters.Length > MAXPARAMETERS)
        {
            throw new ArgumentException("AuditTrail: to many parameters passed.  " + parameters.ToString());
        }
... some code omitted
    }

    protected AuditTrail()
    {
        this.Init();
    }

    public virtual int AID { get; set; }
    public virtual DateTime AuditTime { get; set; }
    public virtual Bearbeiter User { get; set; }
    public virtual int Bearbeiter_ID
    {
        get
        {
            return (this.User != null) ? this.User.Bearbeiter_Id : -1;
        }
        set
        {
            this.SetUser(value);
        }
    }
    public virtual string Benutzername
    {
        get
        {
            if (this.User == null)
            {
                return string.Empty;
            }
            return this.User.Benutzername ?? string.Empty;
        }
        protected set
        {
        }
    }
    public virtual string HostName { get; set; }
    public virtual AuditTrailDef AuditTrailDefObj { get; set; }
    public virtual int Type
    {
        get
        {
            return this.AuditTrailDefObj != null ? (int)this.AuditTrailDefObj.Type : -1;
        }
        set
        {
            this.SetAuditTrailType((AuditTrailType)value);
        }
    }
    public virtual string Name
    {
        get
        {
            return this.AuditTrailDefObj != null ? this.AuditTrailDefObj.Name : null;
        }
    }
    public virtual string Para1 { get; set; }
    public virtual string Para2 { get; set; }
    public virtual string Para3 { get; set; }
    public virtual string Para4 { get; set; }

    /// <summary>Initialize this AuditTrail instance</summary>
    protected void Init()
    {
        try
        {
            this.AuditTime = DateTime.Now;
            this.HostName = Environment.MachineName;
            this.Bearbeiter_ID = DAL.CurrentMeCISUser_Bearbeiter_Id;
        }
        catch (Exception ex)
        {
            log.Warn("Init failed but ignored", ex);
        }
    }

    protected void SetAuditTrailType(AuditTrailType type)
    {
        AuditTrailDef atd = DAL.Repository.GetById<AuditTrailDef>((int)type);
        if (atd == null)
        {
            throw new ArgumentException("SetAuditTrailType: type" + type.ToString() + " not found");
        }
        this.AuditTrailDefObj = atd;
    }

    /// <summary>set a reference to an user (BEARBEITER) instance</summary>
    /// <param name="bearbeiter_ID">id of user to set (BEARBEITER.BEARBEITER_ID)</param>
    protected void SetUser(int bearbeiter_ID)
    {
        Bearbeiter user = DAL.Repository.GetById<Bearbeiter>(bearbeiter_ID);
        if (user == null)
        {
            throw new ArgumentException("SetUser: invalud bearbeiter_id" + bearbeiter_ID.ToString());
        }
        this.User = user;
    }
}
}

AuditTrailTestSpecSetState:

public class AuditTrailTestSpecSetState : AuditTrail
{

    public virtual int Id
    {
        get
        {
            int n = int.Parse(this.Para1);
            return n;
        }
        protected set
        {
        }
    }

    public virtual TestSpecStates State
    {
        get
        {
            int n = int.Parse(this.Para2);
            return (TestSpecStates)n;
        }
    }

    public virtual string StateDesc
    {
        get
        {
            TestSpecStates rs = this.State;
            string s = rs.ToString();
            try 
            {
                s = DAL.RscMgr.GetString("TestSpecState_" + s, CultureInfo.CurrentCulture);
            }
            catch (Exception)
            {
                log.Error("StateDesc: no rsc for state " + this.State.ToString());
            }                
            return s;
        }
    }

    public virtual int StatusVal
    {
        get
        {
            return (int)this.State;
        }
    }
}

堆栈跟踪/记录: SQL语句对我来说似乎没问题。

...Com.XY.App.MgmtTool.TestSpecMgmtForm: ShowHistoryDataGrid
Com.XY.App.DAL.GenericDAOHibernate`2: GetTestSpecHistory id:1479

**NHibernate.SQL: 2012-12-12 08:26:42,488 DEBUG NHibernate.SQL: select setstatete0_.AID as AID6_, setstatete0_.DATUM as DATUM6_, setstatete0_.BEARBEITER_ID as BEARBEITER3_6_, setstatete0_.RECHNER as RECHNER6_, setstatete0_.AKTIONSCODE as AKTIONSC5_6_, setstatete0_.PARAMETER1 as PARAMETER6_6_, setstatete0_.PARAMETER2 as PARAMETER7_6_, setstatete0_.PARAMETER3 as PARAMETER8_6_, setstatete0_.PARAMETER4 as PARAMETER9_6_ from App_OWNER.AUDITTRAIL setstatete0_ where case when setstatete0_.aktionscode=20005 then '1' when setstatete0_.aktionscode=20010 then '2' when setstatete0_.aktionscode=20020 then '3' else '10' end='3' and setstatete0_.PARAMETER1=:p0 and setstatete0_.AKTIONSCODE=:p1 order by setstatete0_.AID desc;:p0 = '1479' [Type: String (0)], :p1 = 20020 [Type: Int32 (0)]**

Eine Ausnahme (erste Chance) des Typs "NHibernate.WrongClassException" ist in NHibernate.dll aufgetreten.
Eine Ausnahme (erste Chance) des Typs "NHibernate.WrongClassException" ist in NHibernate.dll aufgetreten.
Eine Ausnahme (erste Chance) des Typs "NHibernate.WrongClassException" ist in NHibernate.dll aufgetreten.
Eine Ausnahme (erste Chance) des Typs "NHibernate.WrongClassException" ist in NHibernate.dll aufgetreten.
Com.XY.App.MgmtTool.TestSpecModel: 2012-12-12 08:26:42,754 DEBUG Com.XY.App.MgmtTool.TestSpecModel: GetTestSpecHistory failed!

**NHibernate.WrongClassException: Object with id: 5436 was not of the specified subclass:** SetStateTestSpec (loading object was of wrong class [Com.XY.App.DAL.Entities.AuditTrail])
   bei NHibernate.Loader.Loader.InstanceAlreadyLoaded(IDataReader rs, Int32 i, IEntityPersister persister, EntityKey key, Object obj, LockMode lockMode, ISessionImplementor session) in p:\nhibernate-core\src\NHibernate\Loader\Loader.cs:Zeile 896.

   bei NHibernate.Loader.Loader.GetRow(IDataReader rs, ILoadable[] persisters, EntityKey[] keys, Object optionalObject, EntityKey optionalObjectKey, LockMode[] lockModes, IList hydratedObjects, ISessionImplementor session) in p:\nhibernate-core\src\NHibernate\Loader\Loader.cs:Zeile 872.
   bei NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) in p:\nhibernate-core\src\NHibernate\Loader\Loader.cs:Zeile 342.
   bei NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in p:\nhibernate-core\src\NHibernate\Loader\Loader.cs:Zeile 473.
   bei NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in p:\nhibernate-core\src\NHibernate\Loader\Loader.cs:Zeile 251.
   bei NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in p:\nhibernate-core\src\NHibernate\Loader\Loader.cs:Zeile 1569.
   bei NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) in p:\nhibernate-core\src\NHibernate\Loader\Loader.cs:Zeile 1472.
   bei NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) in p:\nhibernate-core\src\NHibernate\Loader\Loader.cs:Zeile 1467.
   bei NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters) in p:\nhibernate-core\src\NHibernate\Hql\Ast\ANTLR\Loader\QueryLoader.cs:Zeile 288.
   bei NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters) in p:\nhibernate-core\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs:Zeile 112.
   bei NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) in p:\nhibernate-core\src\NHibernate\Engine\Query\HQLQueryPlan.cs:Zeile 105.
   bei NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results) in p:\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:Zeile 626.
   bei NHibernate.Impl.SessionImpl.List(String query, QueryParameters parameters) in p:\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:Zeile 592.
   bei NHibernate.Impl.QueryImpl.List() in p:\nhibernate-core\src\NHibernate\Impl\QueryImpl.cs:Zeile 64.
   bei Com.XY.App.DAL.TestSpecDAOHibernate.GetTestSpecHistory(Int32 id) in L:\App\DAL\DAOHibernate\TestSpecDAOHibernate.cs:Zeile 55.
   bei Com.XY.App.MgmtTool.TestSpecModel.GetTestSpecHistory(Int32 id) in L:\App\MgmtTool\Model\TestSpecModel_Mgmt.cs:Zeile 221.

Com.XY.App.MgmtTool.FrmHelper: 2012-12-12 08:26:42,760 DEBUG Com.XY.App.MgmtTool.FrmHelper: ColorizeZRDataGrid 6 0

1 个答案:

答案 0 :(得分:1)

插入AuditTrail条目并立即读取审核跟踪列表(包含新条目)后出现问题

为了插入我创建了一个AuditTrail对象(不是特定的AuditTrailTestSpecSetState实例)

从数据库的角度来看,这无关紧要;

从nHibernate的角度来看,它有所不同,将新创建的对象保存在RAM中,错误的&#34;班级类型。

(这就是为什么重新启动应用程序之后一切正常,没有缓存中的错误对象)