【问题标题】:NHibernate : unexpected session trouble when persisting objectNHibernate:持久对象时出现意外会话问题
【发布时间】:2011-07-26 22:50:45
【问题描述】:

我在处理一些 NHibernate 代码时遇到了问题。基本上,我试图尽可能缩短会话生命周期,以尽量减少应用程序中的状态信息。

我发现如果不具体描述我的问题是相当困难的,所以我将继续使用文章和类别的隐喻。

public class Article
{
    public virtual long Id { get; set; }
    public virtual string Name { get; set; }
    public virtual Category Category { get; set; }
}
public class Category
{
    public virtual long Id { get; set; }
    public virtual string Name { get; set; }
    public override string ToString() { return "cat-" + this.Id.ToString(); }
}
public class ArticleMapping : ClassMap<Article>
{
    public ArticleMapping()
    {
        this.Id( x => x.Id, "id" ).GeneratedBy.Assigned();
        this.Map( x => x.Name, "name" );
        this.References( x => x.Category ).Fetch.Join().Cascade.None();
    }
}
public class CategoryMapping : ClassMap<Category>
{
    public CategoryMapping()
    {
        this.ReadOnly();
        this.Id(x => x.Id, "id").GeneratedBy.Assigned();
        this.Map(x => x.Name, "name");
    }
}

我要做的是创建一个新的文章,为其命名,从通过下述方法加载的列表中分配一个类别,然后尝试保存。 p>

我收到以下警告:

无法确定分配标识符的 cat-1 是暂时的还是分离的

如果您查看模型和映射代码,您会发现 cat-1 根本不应该被持久化 - 它是一个类别并且定义为只读且非级联。

//code that loads the list of categories
IStatelessSession session = this.SessionService.GetStatelessSession();
IList<Category> cats = session.CreateCriteria<Category>().List<Category>();
this.SessionService.EndSession(session);

//code that's called to save the instance
ISession session = this.SessionService.GetSession();
using (ITransaction transaction = session.BeginTransaction())
{
  session.SaveOrUpdate(article);
  transaction.Commit();
}
this.SessionService.EndSession(session);

如果我再次调用 Save 方法,一切都会变成香蕉形状:

例外:

NHibernate.StaleStateException:意外的行数:0;预计:1

堆栈跟踪:

在 NHibernate.AdoNet.Expectations.BasicExpectation.VerifyOutcomeNonBatched(Int32 rowCount, IDbCommand 语句) 在 NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation 期望)

在 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)

在 NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)

在 NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFieldA 第一次机会异常类型 'NHibernate.StaleStateException' 发生在 NHibernate.dll s, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session)

在 NHibernate.Action.EntityUpdateAction.Execute()

在 NHibernate.Engine.ActionQueue.Execute(IExecutable 可执行文件)

在 NHibernate.Engine.ActionQueue.ExecuteActions(IList 列表)

在 NHibernate.Engine.ActionQueue.ExecuteActions()

在 NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource 会话)

我以前认为 NHibernate 没有黑魔法,但这让我想拜访我的巫毒牧师,向另一个领域寻求帮助......

有人知道 StaleStateException 来自哪里吗?这次我哪里做错了?

提前致谢

塞比

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate persistence


    【解决方案1】:

    不确定,但问题可能在于您使用一个会话加载对象,并使用另一个会话对其进行更新。
    在那种情况下,对象确实是分离的。
    尝试使用 Bind() 函数将对象绑定到第二个会话,或者考虑只使用一个会话(注意会话!= db 连接。意思是打开一个会话不应该太昂贵,而且不是一个坏主意) .

    【讨论】:

    • 我提到的最初警告可能可以追溯到这个事实,类别加载在 session1 中,文章存储在 session2 中。由于 session1 是无状态的,这应该就像只使用瞬态对象...... Bind 方法属于哪个类?
    【解决方案2】:

    呸!有时,在向世界大喊大叫之前检查所有本地内容会有所帮助……某处的数据库触发器覆盖了 NHibernate 从序列中获取的 ID。

    意思:

    • 警告是完全可以理解的, 作为分配给 文章没有会话状态,因此 必须通过 fetch 或 或者 session.Refresh(), 结果相同。

    • StaleObjectStateException 必须 发生,因为该行,正在 持续存在,无法定位 桌子(谢谢,Trigger 先生!)

    很抱歉打扰你们了……

    【讨论】:

    • 我正在做一些不同的事情,但我也有一个触发器在某些条件下更改 ID。所以,感谢您回答自己的问题;你让我免于数小时的沮丧。
    猜你喜欢
    • 2020-04-26
    • 2011-06-29
    • 2012-03-31
    • 2013-05-10
    • 2015-12-18
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    • 2017-04-03
    相关资源
    最近更新 更多