插入实体后NHibernate“null identifier”异常

时间:2009-06-11 17:32:43

标签: nhibernate

我在将实体保存到SQL Server 2005数据库时遇到问题。我正在使用NHibernate 2.0.0.3002作为我的持久层。映射是典型的,带有整数ID,如下所示

<id name="Id" unsaved-value="0">
  <column name="Id"/>
  <generator class="identity" />
</id>

为简洁起见,我省略了其余部分。该应用程序使用具有通用保存方法的存储库类,如下所示

public void Save(T toSave)
{
    Save(new T[] { toSave });
}

public void Save(IEnumerable<T> toSave)
{
    using (ISession session = SessionFactory.OpenSession())
    {
        foreach (T item in toSave)
        {
            session.SaveOrUpdate(item);
        }
        session.Flush();
    }
}

在会话上调用SaveOrUpdate时,会抛出一个带有“null identifier”消息的异常。当我检查数据库时,已插入所有正确值的行,所以我认为问题是当NHibernate尝试使用@@ IDENTITY返回的值设置实体的Id属性时。我可以通过SQL Profiler看到正在调用@@ IDENTITY,所以我不明白为什么会抛出异常。

还有其他人有这个问题吗?

5 个答案:

答案 0 :(得分:8)

保存和删除都必须在事务中发生,并且事务必须在最后提交。

像这样:

public void Save(IEnumerable<T> toSave)
{
    using (ISession session = SessionFactory.OpenSession())
    {
        ITransaction transaction = Session.BeginTransaction();

        foreach (T item in toSave)
        {
            session.SaveOrUpdate(item);
        }

        transaction.Commit();           
        session.Flush();
    }
}

请注意:您希望将其包含在正在使用和正确回滚中...此外,根据您的方案,放置您打开和提交事务的位置也很重要。你也应该在完成后关闭交易......

另外,你能详细说明发生异常的地方吗?听起来你正在保存一个父母,然后孩子正在投掷,因为父母的id为空?或者,它实际上是在拯救父母吗?

答案 1 :(得分:1)

配置log4net可能会有所帮助,以便您可以记录和查看NHibernate正在执行的操作......

我曾经遇到过使用Access的NHibernate的问题,并且能够通过设置日志记录来解决它,以便我可以准确找出问题的原因。

我收到的错误消息与您的错误消息不同,但this是我描述如何解决问题的文章。也许它对你有所帮助。 :)

答案 2 :(得分:0)

NHibernate开发人员非常劝阻身份。我们遇到的主要问题是,在您冲洗之前,您不会获得ID。在您的Int案例中,HiLo将是一个很好的替代品。

话虽如此,我认为你真的想要这样做......

<id name="Id" column="Id" unsaved-value="0">
   <generator class="identity"/>  
</id>

答案 3 :(得分:0)

我也遇到了这个错误,解决方法是将其包装在Ben提到的事务中。然而,我不能让Ben和gilles27代码工作 - 可能是因为我对泛型和NHibernate不熟悉。我创建了一个稍微不同的实现(使用Fluent NHibernate v1.3):

        public static ISession LocalDbSession = null;

    public static void Save<T>(T toSave)
    {
        using (var transaction = LocalDbSession.BeginTransaction())
        {
            LocalDbSession.Save(toSave);
            transaction.Commit();
            LocalDbSession.Flush();
        }
    }

    public static void Save<T>(IEnumerable<T> toSave)
    {
        using (var transaction = LocalDbSession.BeginTransaction())
        {
            foreach (T item in toSave)
            {
                LocalDbSession.Save(item);
            }

            transaction.Commit();
            LocalDbSession.Flush();
        }
    }

答案 4 :(得分:-2)

我认为不是生成器类=“身份”/&gt;

尝试generator class =“guid.comp”