无法使用NHibernate进行更新或插入

时间:2012-06-22 06:45:53

标签: nhibernate save

我在使用Oracle 8i客户端的旧数据库上使用NHibernate。我可以在数据库表上执行Get和Delete,但无法保存或更新条目。例外情况如下,sqlString由问号组成,我不知道为什么。

Nhibernate.Exceptions.GenericADOException:

    {"could not update: [MIAP.Domain.Entities.MITFORG#3][SQL: UPDATE MITFORG SET TREELEVEL = ?, PARTENTID = ?, FORGNAME = ?, FORGINFO = ?, ACTIVE = ?, MUTATOR = ?, INPDATETIME = ?, UPDDATETIME = ? WHERE FORGID = ?]"}

这是我的实体类和映射:

public class MITFORG {
    private long fORGID;
    private long? tREELEVEL;
    private long? pARTENTID;
    private string fORGNAME;
    private string fORGINFO;
    private string aCTIVE;
    private long? mUTATOR;
    private DateTime? iNPDATETIME;
    private DateTime? uPDDATETIME;
    public MITFORG() { }
    public virtual long FORGID {
        get {
            return this.fORGID;
        }
        set {
            this.fORGID = value;
        }
    }
    public virtual long? TREELEVEL
    {
        get {
            return this.tREELEVEL;
        }
        set {
            this.tREELEVEL = value;
        }
    }
    public virtual long? PARTENTID
    {
        get {
            return this.pARTENTID;
        }
        set {
            this.pARTENTID = value;
        }
    }
    public virtual string FORGNAME {
        get {
            return this.fORGNAME;
        }
        set {
            this.fORGNAME = value;
        }
    }
    public virtual string FORGINFO {
        get {
            return this.fORGINFO;
        }
        set {
            this.fORGINFO = value;
        }
    }
    public virtual string ACTIVE {
        get {
            return this.aCTIVE;
        }
        set {
            this.aCTIVE = value;
        }
    }
    public virtual long? MUTATOR
    {
        get {
            return this.mUTATOR;
        }
        set {
            this.mUTATOR = value;
        }
    }
    public virtual DateTime? INPDATETIME
    {
        get {
            return this.iNPDATETIME;
        }
        set {
            this.iNPDATETIME = value;
        }
    }
    public virtual DateTime? UPDDATETIME
    {
        get {
            return this.uPDDATETIME;
        }
        set {
            this.uPDDATETIME = value;
        }
    }
}



<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping assembly="MIAP.Domain" namespace="MIAP.Domain.Entities" xmlns="urn:nhibernate-mapping-2.2">
  <class name="MITFORG" table="MITFORG" lazy="true" >
    <id name="FORGID">
      <generator class="assigned" />
    </id>
    <property name="TREELEVEL"></property>
    <property name="PARTENTID"></property>
    <property name="FORGNAME"></property>
    <property name="FORGINFO"></property>
    <property name="ACTIVE"></property>
    <property name="MUTATOR"></property>
    <property name="INPDATETIME"></property>
    <property name="UPDDATETIME"></property>
  </class>
</hibernate-mapping>

我检查了属性名称和表列名称。由于FORGID是由应用程序分配的,因此我将生成器类更改为“已分配”。它也不适用于“身份”。有人可以指点我调试这个的方向吗?

已编辑:保存条目的代码

    Dim mitforgRepository As New MITFORGRepository
    Dim mitforg As MITFORG = mitforgRepository.GetById(3)
    mitforg.FORGINFO = "T"
    mitforg.ACTIVE = "Y"
    mitforg.FORGINFO = "T"
    mitforg.INPDATETIME = Now
    mitforg.MUTATOR = 324
    mitforg.PARTENTID = 335
    mitforg.TREELEVEL = 1
    mitforg.UPDDATETIME = Now
    mitforgRepository .Save(mitforg)

这是Repository类:

using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using MIAP.Domain.Entities;

namespace MIAP.Domain.Repositories
{
    public class MITFORGRepository : IRepository<MITFORG, Int64?>
    {
        private static ISession GetSession()
        {
            return SessionProvider.SessionFactory.OpenSession();
        }

        public MITFORG GetById(Int64? id)
        {
            using (ISession session = GetSession())
            {
                return session.Get<MITFORG>(id);
            }
        }

        public void Save(MITFORG saveObj)
        {
            using (ISession session = GetSession())
            {
                using (ITransaction trans = session.BeginTransaction())
                {
                    session.SaveOrUpdate(saveObj);
                    trans.Commit();
                }
            }
        }

        public void Delete(MITFORG delObj)
        {
            using (ISession session = GetSession())
            {
                using (ITransaction trans = session.BeginTransaction())
                {
                    session.Delete(delObj);
                    trans.Commit();
                }
            }
        }
    }
}

InnerException是System.Data.OracleClient.OracleException,ORA-12571

这是堆栈跟踪:

   於 System.Data.OracleClient.OracleConnection.CheckError(OciErrorHandle errorHandle, Int32 rc)
   於 System.Data.OracleClient.OracleCommand.Execute(OciStatementHandle statementHandle, CommandBehavior behavior, Boolean needRowid, OciRowidDescriptor& rowidDescriptor, ArrayList& resultParameterOrdinals)
   於 System.Data.OracleClient.OracleCommand.ExecuteNonQueryInternal(Boolean needRowid, OciRowidDescriptor& rowidDescriptor)
   於 System.Data.OracleClient.OracleCommand.ExecuteNonQuery()
   於 NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd) 於 c:\Users\oskar.berggren\Documents\Projects\nhibernate-core-3\src\NHibernate\AdoNet\AbstractBatcher.cs: 行 203
   於 NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation expectation) 於 c:\Users\oskar.berggren\Documents\Projects\nhibernate-core-3\src\NHibernate\AdoNet\NonBatchingBatcher.cs: 行 40
   於 NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session) 於 c:\Users\oskar.berggren\Documents\Projects\nhibernate-core-3\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs: 行 2799

3 个答案:

答案 0 :(得分:0)

如果您正在使用已分配的ID,则无法使用SaveOrUpdate,因为NHibernate不会知道它是新实例(即保存/执行插入)还是现有实例(即更新)。

然后,您需要明确是否要插入新实体(session.Save)或更新现有实体(session.Update)。

答案 1 :(得分:0)

从它的外观来看,你想创建一个新对象并将其保存到数据库中,但你正在做的是使用Nhibernate Session加载对象然后更新它的属性..这告诉Nhibernate会话就是你在db中有一个与给定id相关联的对象,现在你想要更新某些属性,当你想要一个insert语句运行时。

因此,正确的方法是创建一个新的MitForg对象,然后在其上调用Session.SaveOrUpdate(),Nhibernate应该在此后进行插入。

您也可以尝试使用Session.Merge()

请告诉我这是否适合您..

答案 2 :(得分:0)

原来这是一个Unicode到ASCII的转换问题。我按照以下链接中的解决方案。我们需要的是在映射文件中为所有字符串类型属性添加一个type属性,如下所示:

<property name="FORGNAME"  type="AnsiString" ></property>

最近我的同事也遇到了某种Unicode / ASCII转换问题,但我从未想过它会是答案。异常消息只是误导......

感谢Martin提出鼓舞人心的建议!

NHibernate and The Case of the Crappy Oracle NHibernate and ORA-12571 Errors