NHibernate:持久化对象时意外的会话故障

时间:2011-03-31 14:09:19

标签: c# nhibernate fluent-nhibernate persistence

我遇到了一些NHibernate Code.Basically我试图让会话生命周期尽可能短,以尽量减少应用程序中的状态信息。

我觉得很难描述我的问题而不具体,所以我会继续使用文章和类别的比喻。

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");
    }
}

我所做的是创建一个新的文章,为其命名,从通过下述方法加载的列表中指定类别并尝试保存。

我收到以下警告:

  

无法确定指定标识符的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

Stacktrace:

at NHibernate.AdoNet.Expectations.BasicExpectation.VerifyOutcomeNonBatched(Int32 rowCount,IDbCommand statement) 在NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation expectation)

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

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

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

在NHibernate.Action.EntityUpdateAction.Execute()

at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)

at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)

在NHibernate.Engine.ActionQueue.ExecuteActions()

at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)

我曾经认为NHibernate没有黑魔法,但是这让我想去拜访我的伏都教牧师,寻求其他领域的帮助......

有没有人知道StaleStateException来自哪里?这次我哪里出错?

提前致谢

塞比

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

含义:

  • 警告完全可以理解, 作为分配给的类别 文章没有会话状态,所以 hasto通过获取或确定 或者session.Refresh(), 结果相同。

  • StaleObjectStateException必须 发生,因为行,是 执着,无法定位 桌子(谢谢,Trigger先生!)

很抱歉打扰你们......