2011-03-31 33 views
2

我遇到了一些NHibernate Code.Basically问题,我试图保持会话生存期尽可能短,以尽量减少应用程序中的状态信息。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"); 
    } 
} 

我要做的就是创建一个新的,给它一个名字,从通过下面描述的方法加载列表分配类别并尝试保存。

我得到以下警告:

无法确定是否CAT-1与分配的标识符是瞬时的或脱

如果你看看模型和映射代码,你会看到猫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期望)

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

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会话)

在NHibernate.Persister.Entity.AbstractEntityPersister.Update(对象ID,对象[]字段的Int32 []类型的dirtyFieldA第一次机会异常 'NHibernate.StaleStateException' 发生在NHibernate.dll S,布尔hasDirtyCollection ,Object [] oldFields,Object oldVersion,Object obj,Object rowId,ISessionImplementor session)

at NHibernate.Action.Ent ityUpdateAction.Execute()

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

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

在NHibernate.Engine.ActionQueue.ExecuteActions()

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

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

有没有人有任何想法,哪里StaleStateException来自?这次我错了哪里?

在此先感谢

塞比

回答

1

Yuck!有时候,在向全世界大声呼喊之前检查所有本地的东西是有帮助的......有一个数据库触发器覆盖了NHibernate从序列中提取的ID。

含义:

  • 的警告是充分理解,如 分配给 文章的类别没有会话状态,从而使 hasto通过确定取或可替代地 session.Refresh( ), ,它有相同的结果。

  • 的StaleObjectStateException不得不 发生,自排,是 持续性,不能设在 表(感谢,触发先生!)

抱歉打扰你们。 ..

+0

我正在做一些不同的事情,但我也有一个触发器在某些条件下改变了ID。所以,谢谢你回答你自己的问题。你从沮丧时间中拯救了我。 – Krauss 2017-03-22 02:58:55

2

不知道,但这个问题可能是您加载使用一个会话对象,并使用另一个更新的事实。
在这种情况下,对象确实是分离的。
尝试使用Bind()函数将对象绑定到第二个会话,或考虑只使用一个会话(请注意,会话!= db连接。含义 - 打开会话不应该太昂贵,并且不是太差理念)。

+0

我引用的初始警告可能会回到这个事实,类别在session1中加载,而文件在session2中存储。由于session1是无状态的,因此应该像处理瞬态对象一样...... Bind方法属于哪个类? – 2011-04-01 06:31:41