nHibernate神秘地从多对一关系中删除项目

时间:2013-01-14 12:45:10

标签: c# .net nhibernate

我有一个简单的应用程序,用户可以打开订单,对它们进行更改,然后将它们保存回数据库。当订单打开时,我会像这样从数据库中检索它

ISession session = SessionFactory.OpenSession();

...

Order order = session.Query<Order>()
                     .Where(o => o.Id == id)
                     .FirstOrDefault();

要启用延迟加载order.Comments,我会保持会话处于打开状态,直到订单关闭为止。以下是映射:

<class name="Order">
    <id name="Id">
        <generator class="identity" />
    </id>    

...

    <set name="Comments" access="field.camelcase-underscore" cascade="all-delete-orphan"    lazy="true" order-by="Created">
      <key column="OrderId" />
      <one-to-many class="Comment" />
    </set>     
</class>

<class name="Comment" table="OrderComment" lazy="false">
    <id name="Id">
      <generator class="identity" />
    </id>
    <many-to-one name="Author" />
    <property name="Created" />
    <property name="Text" length="1000" />
</class>

该应用程序的设计是为了在订单打开时,可以在关闭之前保存多次。我这样保存:

using (ITransaction trans = session.BeginTransaction())
{
    session.SaveOrUpdate(order)
    trans.Commit();
}

最后,当用户关闭订单时,我会处理会话。

这里有问题:如果用户添加评论,保存,然后在关闭订单之前添加另一条评论并再次保存,则在第二次保存期间删除第一条评论。这是从第二次保存输出的sql:

NHibernate: INSERT INTO OrderComment (Id, Author, Created, Text) VALUES (hibernate_sequence.nextval, :p0, :p1, :p2) returning Id into :nhIdOutParam;:p0 = 1 [Type: Int32 (0)], :p1 = 14.01.2013 12:53:20 [Type: DateTime (0)], :p2 = '2' [Type: String (0)], :nhIdOutParam = NULL [Type: Int32 (0)]

**NHibernate: UPDATE OrderComment SET OrderId = null WHERE OrderId = :p0 AND Id = :p1;:p0 = 465 [Type: Int32 (0)], :p1 = 591 [Type: Int32 (0)]**

NHibernate: UPDATE OrderComment SET OrderId = :p0 WHERE Id = :p1;:p0 = 465 [Type: Int32 (0)], :p1 = 592 [Type: Int32 (0)]

所以问题是粗线 - 第一条评论的OrderId被设置为null。谁能告诉我为什么?

我在这里使用nHibernate的方式有什么问题吗?重申我的所作所为:

  1. 打开会话
  2. 检索对象
  3. 用户更新对象
  4. 通过开始一个事务来保存对象,调用session.SaveOrUpdate(object),然后提交事务。
  5. 重复步骤3和4任何次数。
  6. 处理会话。
  7. 这是否可以使用nHibernate

    修改

    以下是Order类中的comments属性:

    ICollection<Comment> _comments = new List<Comment>();
    public virtual ReadOnlyCollection<Comment> Comments
    {
        get 
        {
            return _comments.ToList().AsReadOnly(); 
        }
    }
    

    然后通过调用以下方法添加注释:

    public virtual void AddComment(Comment comment)
    {
        _comments.Add(comment);    
    }
    
     ...
    
    Comment comment = new Comment()
    {
        Author = User.Current,
        Created = DateTime.Now,
        Text = text
    };
    
    order.AddComment(comment);
    

    这是Comment类。 Id在基类PersistentObject<T>中实现:

    public class Comment : PersistentObject<int>
    {        
        public User Author { get; private set; }
        public DateTime Created { get; private set; }
        public string Text { get; private set; }                                             
    }
    
    public abstract class PersistentObject<T>
    {        
        public virtual T Id { get; protected internal set; }       
    
        public override bool Equals(object obj)
        {
            // If both objects have not been saved to database, then can't compare Id because this
            // will be 0 for both.  In this case use reference equality.
    
            PersistentObject<T> other = obj as PersistentObject<T>;
            if (other == null)
                return false;
    
            bool thisIsDefault = object.Equals(Id, default(T));
            bool otherIsDefault = object.Equals(other.Id, default(T));
    
            if (thisIsDefault && otherIsDefault)
                return object.ReferenceEquals(this, other);
            else if (thisIsDefault || otherIsDefault)
                return false;
            else
                return object.Equals(this.Id, other.Id);
        }
    
        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }        
    }
    

2 个答案:

答案 0 :(得分:1)

您能否显示用于将项目添加到评论集合的代码?

您需要让NHibernate管理注释集合,因此请确保您没有将Comments属性重新设置为new List<OrderComment>或类似的东西,请确保您保留相同的NHibernate实例化代理并添加/删除/必要时清除其值。

答案 1 :(得分:1)

我认为HashCode不应该来自IdOrder.Comments是一个基于哈希的集合。评论的开头都有Id 0。添加到集合时,HashCode0