Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# nHibernate神秘地从多对一关系中删除项目_C#_.net_Nhibernate - Fatal编程技术网

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

C# nHibernate神秘地从多对一关系中删除项目,c#,.net,nhibernate,C#,.net,Nhibernate,我有一个简单的应用程序,用户可以打开订单,对其进行更改,然后将其保存回数据库。当打开订单时,我会像这样从数据库中检索它 ISession session = SessionFactory.OpenSession(); ... Order order = session.Query<Order>() .Where(o => o.Id == id) .FirstOrDefault(); 最后,

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

ISession session = SessionFactory.OpenSession();

...

Order order = session.Query<Order>()
                     .Where(o => o.Id == id)
                     .FirstOrDefault();
最后,当用户关闭订单时,我将处理会话

这里有一个问题:如果用户添加注释并保存,然后在关闭订单之前添加另一条注释并再次保存,则第一条注释将在第二次保存期间删除。下面是从第二次保存输出的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的方式有什么问题吗?重申我的工作:

  • 开课
  • 检索对象
  • 用户更新对象
  • 通过启动事务、调用session.SaveOrUpdate(对象),然后提交事务来保存对象
  • 重复步骤3和4任意次数
  • 处理会话
  • 这是使用
    nHibernate
    的可接受方式吗

    编辑

    以下是Order类中的comments属性:

    ICollection<Comment> _comments = new List<Comment>();
    public virtual ReadOnlyCollection<Comment> Comments
    {
        get 
        {
            return _comments.ToList().AsReadOnly(); 
        }
    }
    
    这是注释类。Id在基类
    PersistentObject
    中实现:

    公共类注释:PersistentObject
    {        
    公共用户作者{get;private set;}
    已创建公共日期时间{get;private set;}
    公共字符串文本{get;private set;}
    }
    公共抽象类PersistentObject
    {        
    公共虚拟T Id{get;受保护的内部集;}
    公共覆盖布尔等于(对象对象对象)
    {
    //如果两个对象都未保存到数据库,则无法比较Id,因为
    //两者都将为0。在这种情况下,请使用引用相等。
    PersistentObject other=对象作为PersistentObject;
    如果(其他==null)
    返回false;
    bool thisIsDefault=object.Equals(Id,默认值(T));
    bool otherIsDefault=object.Equals(other.Id,默认值(T));
    if(thisIsDefault&&otherIsDefault)
    return object.ReferenceEquals(this,other);
    else if(thisIsDefault | | otherIsDefault)
    返回false;
    其他的
    返回object.Equals(this.Id,other.Id);
    }
    公共覆盖int GetHashCode()
    {
    返回Id.GetHashCode();
    }        
    }
    
    能否显示用于将项目添加到评论集合的代码


    您需要让NHibernate管理注释集合,因此请确保您没有将注释属性重新设置为
    新列表
    或类似内容,确保保留相同的NHibernate实例化代理,并根据需要添加/删除/清除其值。

    我不认为
    HashCode
    应该取自
    Id
    Order.Comments
    是一个集合,它基于散列。所有注释的开头都有一个Id
    0
    。当添加到集合中时,将使用
    HashCode
    ,当它为
    0

    时,谢谢您的回答。我已经用更多信息更新了我的问题。我绝对不会重新设置_comments字段。我唯一一次设置它是在字段初始化器中,之后nHibernate设置了它,我使用它。消息ID从哪里来?对不起,应该是OrderId。是的,这就是问题所在!如果我删除了对GetHashCode的覆盖,那么nHibernates不会在第二次保存时删除第一条注释。但我不明白这为什么会造成问题。在看到您的答案后,我尝试将收藏从一套改为一个包,这也解决了问题。所以我猜nHibernate决定了这两条评论是相等的,只允许其中一条进入集合,就必须删除另一条。但是我的Equals override对于这2条注释永远不会返回true,那么为什么我错误的GetHashCode实现导致了这个错误呢?对于任何感兴趣的人来说,这是一个如何正确实现GetHashCode()的建议。我不知道,这很奇怪。当我乱搞散列代码时,我还体验到了用词上的奇怪行为。我学到的一件事是,它永远不应该改变它的值,这使得NH或DB创建的id是一个糟糕的候选者。在我们当前的项目中,我们使用的guid不是主键,而是用于此类标识。
    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)]
    
    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);
    
    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();
        }        
    }