0

WinForms アプリケーション、NHibernate v3.3.x、.Net 4、Windows 7 (32 ビット)、Oracle 10g バックエンド

AuditTrail列アクション タイプ (AKTIONSCODE) が追加の (オプションの) パラメータ (Para1-Para4) の意味を制御するテーブルを持つレガシー データベースを使用しています。

対応するクラスを作成しましたAuditTrail。とのような派生サブクラスは、共通パラメーターの適切なゲッターとセッターを取得することのみを目的としていますAuditTrailAsmRuleSetStateAuditTrailTestSpecSetState

エントリの挿入は正常に機能しています。

AuditTrailAsmRuleSetStateエントリやその他の派生クラスの読み取りも正常に機能しています。

しかし、AuditTrailTestSpecSetState エントリを読み取るときに NHibernate.WrongClassException が発生することがあります。 アプリを閉じて(おそらくセッションを閉じますか?)、同じエントリを再度読み取ると、再び機能します!?

あなたのアドバイスは大歓迎です。

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 は次のようになります: (派生クラスAuditTrailTestSpecObjSetStateAuditTrailAsmRuleSetStateはかなり似ていAuditTrailTestSpecSetStateます)

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

Stacktrace/logging: 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
4

1 に答える 1

1

Problem occured after inserting an AuditTrail entry and immediately reading an audit trail list (containing the new entry)

For inserting I created an AuditTrail object (not a specific AuditTrailTestSpecSetState instance)

From the point of view from the database it doesnt matter;

From the point of view from nHibernate it makes a difference, holding the new created object in RAM with the 'wrong" class type.

(that was the reason why after restarting the application everything worked fine again without the wrong object in the cache)

于 2012-12-12T14:54:14.573 に答える