我遇到了一些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来自哪里?这次我哪里出错?
提前致谢
塞比
答案 0 :(得分:2)
不确定,但问题可能是您使用一个会话加载对象,并使用另一个会话更新它 在那种情况下,对象确实是分离的 尝试使用Bind()函数将对象绑定到第二个会话,或者考虑只使用一个会话(注意会话!=数据库连接。意味着 - 打开会话不应该太昂贵,并且不是一个坏主意)
答案 1 :(得分:1)
呸!有时在向全世界大喊大叫之前检查所有本地内容是有帮助的......在某个地方有一个数据库触发器覆盖了NHibernate从序列中获取的ID。
含义:
警告完全可以理解, 作为分配给的类别 文章没有会话状态,所以 hasto通过获取或确定 或者session.Refresh(), 结果相同。
StaleObjectStateException必须 发生,因为行,是 执着,无法定位 桌子(谢谢,Trigger先生!)
很抱歉打扰你们......