Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.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# 避免锁定';已在会话中(UniqueObjectException)_C#_Nhibernate - Fatal编程技术网

C# 避免锁定';已在会话中(UniqueObjectException)

C# 避免锁定';已在会话中(UniqueObjectException),c#,nhibernate,C#,Nhibernate,当需要再次初始化对象时,我在对象上调用此函数: public virtual void Initialize() { if (!HibernateSessionManager.Instance.GetSession().Contains(this)) { try { HibernateSessionManager.Instance.GetSession() .Lock(th

当需要再次初始化对象时,我在对象上调用此函数:

public virtual void Initialize()
{
    if (!HibernateSessionManager.Instance.GetSession().Contains(this)) {

        try
        {
            HibernateSessionManager.Instance.GetSession()
                             .Lock(this, NHibernate.LockMode.None);
        }
        catch (NonUniqueObjectException e) { }
    }
}
我原以为通过检查
包含(this)
可以防止两次初始化某个对象,但有时
锁(this,NHibernate.LockMode.None)
会抛出
非请求对象异常。到目前为止,我忽略了它,因为它是有效的,但我想知道原因和更好的方法来锁定我的对象


最好的问候,Expecto这很可能意味着你在某个地方违反了身份地图。这意味着您有两个具有相同数据库ID但引用标识不同的对象实例

Contains将检查引用相等性,但如果会话中已经存在具有相同类型&id的任何内容,则Lock将抛出异常,这是一个不太严格的比较

考虑以下对AdventureWorks数据库的测试,使用Equals&GetHashCode的简单实现(非常简单且不受推荐)

 using (ISession session = SessionFactory.Factory.OpenSession())
        {
            int someId = 329;

            Person p = session.Get<Person>(someId);
            Person test = new Person() { BusinessEntityID = someId };

            Assert.IsTrue(p.Equals(test)); //your code might think the objects are equal, so you'd probably expect the next line to return true         

            Assert.IsFalse(session.Contains(test)); //But they're not the same object

            Assert.Throws<NonUniqueObjectException>(() =>
            {
                session.Lock(test, LockMode.None); //So when you ask nhibernate to track changes on both objects, it gets very confused
            });
        }
使用(ISession session=SessionFactory.Factory.OpenSession())
{
int-someId=329;
Person p=session.Get(someId);
Person test=new Person(){BusinessEntityID=someId};
Assert.IsTrue(p.Equals(test));//您的代码可能认为对象是相等的,所以您可能希望下一行返回true
Assert.IsFalse(session.Contains(test));//但它们不是同一个对象
Assert.Throws(()=>
{
session.Lock(test,LockMode.None);//因此,当您要求nhibernate跟踪两个对象上的更改时,它会变得非常混乱
});
}
NHibernate(我猜任何ORM)都是通过跟踪对象的变化来工作的。所以在获得329人时,你要求NHibernate注意在一个人的特定实例上发生的任何事情。假设我们把他的名字改成詹姆

接下来,我们将获得另一个具有相同Id的person实例(在本例中,我们只是对其进行了更新,但有许多阴险的方法可以获得这样的对象)。想象一下,NHibernate会让我们将此附加到会话中。我们甚至可以将第二个对象的名字设置为类似Robb的东西

当我们刷新会话时,NHibernate无法知道数据库行是否需要同步到Robb或Jaime。因此,在这一切发生之前,它会将非唯一性抛向你的方向


理想情况下,这些情况不应该突然出现,但如果您非常确定发生了什么,您可能希望签出session.Merge,它允许您将跟踪状态强制为最后一次合并的对象(本例中为Robb).

问题完全不同-如果我不重写
Equals()
,则包含通过引用检查相等性。现在它与我的问题中的代码一起工作

    public override bool Equals(object obj)
    {
        if (this == obj) { 

            return true;
        } 

        if (GetType() != obj.GetType()) {

            return false;
        }

        if (Id != ((BaseObject)obj).Id)
        {

            return false;
        }

        return true;
    }

可能有多个线程试图同时执行此操作?我不明确使用线程。C是否可以自己以某种方式产生这种效果?
merge()
可以,因为在显式调用
save()
之前,我不会多次更改对象。但我不知道该把它放在哪里。在
锁定之前
?只是
合并
,而不是
锁定
?目前我没有得到我所希望的结果。如果没有锁,我会得到
lazyiinitializationexception
,如果使用merge和lock,我仍然会得到
ununiqueobjectexceptions
。我读过关于使用
update
merge
,这取决于具体情况,但据我所知,我无法检查对象是否已经在会话中,至少不能使用
contains()