0

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 像这样:( 派生类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

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

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

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

从 nHibernate 的角度来看,它有所不同,将新创建的对象保存在 RAM 中具有“错误”的类类型。

(这就是为什么在重新启动应用程序后一切都可以正常工作而缓存中没有错误对象的原因)

于 2012-12-12T14:54:14.573 回答