3

为什么在第一次尝试插入模型时从数据库返回错误后我不能只插入模型:

Report report = null;
using (var session = SessionFactory.OpenSession()) {
    try {
        using (var transaction = session.BeginTransaction()) {
            report = new Report();
            session.SaveOrUpdate(report);//Exception: Name field required
            transaction.Commit();
        }
    }
    catch { }

    try {
        using (var transaction = session.BeginTransaction()) {
            report.Name = "theName";
            session.SaveOrUpdate(report);

            //Causes Exception:
            //Row was updated or deleted by another transaction (or unsaved-value 
            //mapping was incorrect): [ReportViewer.DataAccess.Models.Report#22]                          
            transaction.Commit();
        }
    }
    catch { }
}

但是当我更新现有模型时,我得到一个错误,我可以进行修复(在这种情况下设置一个名称)并尝试再次更新:

Report report = null;
using (var session = SessionFactory.OpenSession()) {
    using (var transaction = session.BeginTransaction()) {
        report = new Report();
        report.Name = "theName";
        session.SaveOrUpdate(report);
        transaction.Commit();
    }
}
using (var session = SessionFactory.OpenSession()) {

    //get entity saved from previous session
    report = session.Get<Report>(report.Id);

    try {
        using (var transaction = session.BeginTransaction()) {
            report.Name = null;
            session.SaveOrUpdate(report);//Exception: Name field required
            transaction.Commit();
        }
    }
    catch { }

    try {
        using (var transaction = session.BeginTransaction()) {

            //updates and does not give an error
            report.Name = "theName";
            session.SaveOrUpdate(report);
            transaction.Commit();
        }
    }
    catch { }
}
4

2 回答 2

4

当数据库触发异常时,NHibernate 会话必须关闭(disposed)。不能保证在异常发生后保持一致(内部或与 DB 状态)。

请参阅NHibernate 参考中有关异常处理的章节。

于 2013-02-17T19:34:07.723 回答
2

正如 Oskar 所说,您应该在发生异常后丢弃 NHibernate 会话。但是,插入失败的原因是您已经通过调用SaveOrUpdate它使报告持久化(您应该Save在此处使用)。当您SaveOrUpdate在同一个实例上再次调用时,NHibernate 会抛出异常,因为该对象已经是持久的。如下重写代码可能会让插入成功(但不推荐):

try {
    using (var transaction = session.BeginTransaction()) {
        report.Name = "theName";                   
        transaction.Commit();
    }
}

在更新示例中,调用SaveOrUpdate无效,因为当 NHibernate 加载对象时,该对象变得持久。理解 NHibernate 的实例状态以及如何使用持久对象是基本的并且被广泛误解。

更好的方法是在将对象保存到数据库之前对其进行验证。

于 2013-02-18T15:00:48.443 回答