我一直在使用NHibernate,使用Fluent NHibernate进行映射。我解决了很多问题,并开始认为自己在nhibernate中经验丰富。 但是,这个错误很奇怪。
这是我的模特:
public class MessageNew
{
public virtual int Id { get; set; }
public virtual string Content { get; set; }
public virtual string Subject { get; set; }
public virtual User User { get; set; }
public virtual bool IsSent { get; set; }
public virtual string AmazonMessageId { get; set; }
}
我的映射
public class MessageNewMap : ClassMap<MessageNew>
{
public MessageNewMap()
{
Id(x => x.Id);
Map(x => x.Content).CustomSqlType("text");
Map(x => x.Subject);
Map(x => x.AmazonMessageId);
Map(x => x.IsSent);
References(x => x.User);
}
}
此处发生异常:
foreach (var userToSend in usersToSend)
{
string body = MailHelper.BuildSomeBody()
if (userToSend != CurrentUser)
{
MessageNew message = new MessageNew
{
User = userToSend,
IsSent = false,
Content = body,
Subject = subject
};
session.Save(message); // Exception thrown
}
}
例外情况:
NHibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 1779, of entity: Models.MessageNew
at NHibernate.Engine.StatefulPersistenceContext.CheckUniqueness(EntityKey key, Object obj)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
Id生成器是数据库驱动的自动递增id生成器。 (不是hilo或任何其他)。 NHibernate版本为3.2.0。
我试过重载Equals和GetHashCode,没有运气。
我正在使用的UnitOfWork模式不需要在foreach循环中提交事务或刷新会话。 NHibernate说有另一个具有相同id的对象,但我所做的只是插入一个新对象,它根本没有任何标识符。
我在我的项目中使用相同的结构,除了这个之外,它适用于所有地方。我怀疑它可能是因为&#34;内容&#34; property,是文本并设置为大字符串。
我在这里缺少什么?或者NHibernate遗失了什么?
答案 0 :(得分:4)
有时它会在我们将对象分配给同一个新对象时发生。因此,首先检查您的模型和视图模型,它们不相同。
答案 1 :(得分:4)
我有类似的问题。我经历了很多讨论,教程和论坛,但在写了一些单元测试后,我意识到:
1)session.Contains方法适用于实例
2)session.Save/SaveorUpdate使用ID
此错误显示在session.So中有另一个具有相同ID的对象实例,包含返回false,因为您正在处理不同的实例,并且Save / SaveorUpdate会抛出异常,因为会话中有另一个具有相同ID的对象。 我已经解决了这个问题(我的问题出现在Job Entity中):
Job lJob = lSession.Load<Job>(this.ID);
if(lJob.ID==this.ID)
lSession.Evict(lJob);
lSession.SaveOrUpdate(this);
我希望它可以帮到你
答案 2 :(得分:1)
您可以使用Evict()
从会话中逐出对象,然后您就可以执行任何操作。
当您在另一个会话中拥有相同的对象时,会发生此错误。
答案 3 :(得分:0)
该异常通常表示您有两个单独的对象实例,这些实例具有您尝试在同一会话中管理的相同标识符值。
答案 4 :(得分:0)
您已拥有该ID实体的另一个实例。
两个可能的问题:
1 - 您对实体的比较不起作用。您可以按建议覆盖等于,或者您可以更改在保存之前使用的测试用例:
if (userToSend.Id != CurrentUser.Id)
2 - 您没有为您的实体生成唯一ID,您需要自己分配ID,让NHibernate生成一个或让您的SQL服务器为您执行此操作。在您的映射中暗示应该使用Identity(Fluents默认值),但是您是否已将数据库中的列设置为Identity列?
答案 5 :(得分:0)
我的看法:你没有声明一个Id生成器。因此,只要在会话中获得两个MessageNew实例,它们都将为0作为Id。
答案 6 :(得分:0)
也许有点晚了,但希望这有帮助。
当我尝试在同一会话中使用自动生成的列保存对象的多个实例时,我遇到了类似的问题。我的解决方案是提供不同的值并为每个实体分配它,因此,nhibernates不会将其识别为该实体的相同主键。
答案 7 :(得分:-1)
[..]
};
session.Clear();
session.Save(message);
试试这个,帮助我。
答案 8 :(得分:-1)
在Session.Save
或Session.SaveOrUpdate
Session.Clear();
Session.Flush();
这将使用Session清除所有缓存的实体。