NHibernate,具有相同标识符值的不同对象已与会话关联

时间:2012-03-12 23:54:50

标签: nhibernate fluent-nhibernate

我一直在使用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遗失了什么?

9 个答案:

答案 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.SaveSession.SaveOrUpdate

之前添加以下两行
Session.Clear();
Session.Flush();

这将使用Session清除所有缓存的实体。