asp.net-mvc nhibernate :具有相同标识符值的不同对象已经与会话关联:2,实体:

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2983749/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:21:12  来源:igfitidea点击:

nhibernate : a different object with the same identifier value was already associated with the session: 2, of entity:

asp.net-mvcnhibernate

提问by frosty

I am getting the following error when i tried and save my "Company" entity in my mvc application

当我尝试将我的“公司”实体保存在我的 mvc 应用程序中时出现以下错误

a different object with the same identifier value was already associated with the session: 2, of entity:

具有相同标识符值的不同对象已经与会话关联:2,实体:

I am using an IOC container

我正在使用 IOC 容器

private class EStoreDependencies : NinjectModule
    {
        public override void Load()
        {

            Bind<ICompanyRepository>().To<CompanyRepository>().WithConstructorArgument("session",
                                                                                       NHibernateHelper.OpenSession());
        }
    }

My CompanyRepository

我的公司资料库

public class CompanyRepository : ICompanyRepository
{
    private ISession _session;

    public CompanyRepository(ISession session)
    {
        _session = session;
    }    

    public void Update(Company company)
    {

        using (ITransaction transaction = _session.BeginTransaction())
        {

            _session.Update(company);
            transaction.Commit();
        }
    }

}

}

And Session Helper

和会话助手

public class NHibernateHelper
{
    private static ISessionFactory _sessionFactory; 
    const string SessionKey = "MySession";


    private static ISessionFactory SessionFactory
    {
        get
        {
            if (_sessionFactory == null)
            {
                var configuration = new Configuration();
                configuration.Configure();
                configuration.AddAssembly(typeof(UserProfile).Assembly);
                configuration.SetProperty(NHibernate.Cfg.Environment.ConnectionStringName,
                                          System.Environment.MachineName);
                _sessionFactory = configuration.BuildSessionFactory();
            }
            return _sessionFactory;
        }
    }

    public static ISession OpenSession()
    {
        var context = HttpContext.Current;
        //.GetCurrentSession()

        if (context != null && context.Items.Contains(SessionKey))
        {
            //Return already open ISession
            return (ISession)context.Items[SessionKey];
        }
        else
        {
            //Create new ISession and store in HttpContext
            var newSession = SessionFactory.OpenSession();
            if (context != null)
                context.Items[SessionKey] = newSession;

            return newSession;
        }
    }
}

My MVC Action

我的MVC动作

    [HttpPost]
    public ActionResult Edit(EStore.Domain.Model.Company company)
    {

            if (company.Id > 0)
            {

                _companyRepository.Update(company);
                _statusResponses.Add(StatusResponseHelper.Create(Constants
                    .RecordUpdated(), StatusResponseLookup.Success));
            }
            else
            {
                company.CreatedByUserId = currentUserId;
               _companyRepository.Add(company);
            }


        var viewModel = EditViewModel(company.Id, _statusResponses);
        return View("Edit", viewModel);
    }

回答by Claiton Lovato

I know this is a bit late and you might already found the solution, but maybe others could benefit from it...

我知道这有点晚了,您可能已经找到了解决方案,但也许其他人可以从中受益...

This error is raised from nHibernate when you are updating an instance of an Entity that is saved on the Cache. Basically nHibernate stores your objects on the cache once you loaded it, so next calls would get it from the cache. If you update an instance that is present on the cache nHibernate throws this error otherwise it could cause dirty reads and conflicts regarding loading the old copy of the object. To get around this, you need to remove the object from the cache using the Evict method like:

当您更新保存在缓存中的实体实例时,会从 nHibernate 引发此错误。基本上 nHibernate 将您的对象在加载后存储在缓存中,因此下一次调用将从缓存中获取它。如果更新缓存中存在的实例,nHibernate 会抛出此错误,否则可能会导致脏读和加载对象旧副本时发生冲突。要解决此问题,您需要使用 Evict 方法从缓存中删除对象,例如:

public ActionResult Edit(EStore.Domain.Model.Company company) 
{ 

        if (company.Id > 0) 
        { 
            **ISession.Evict(company);**
            _companyRepository.Update(company);

Hope this helps.

希望这可以帮助。

回答by Joel

I tried @claitonlovatojr's hack, but I couldn't still handle the error.

我尝试了@claitonlovatojr 的 hack,但我仍然无法处理该错误。

All I had to do in my case wasy to replace my ISession.Update(obj)call to ISession.Merge(obj).

在我的情况下,我所要做的就是替换我ISession.Update(obj)ISession.Merge(obj).

In your repository, change:

在您的存储库中,更改:

public void Update(Company company)
{
    using (ITransaction transaction = _session.BeginTransaction())
    {
        //_session.Update(company);
        _session.Merge(company); // <-- this
        transaction.Commit();
    }
}

Also, for more information see this answer.

此外,有关更多信息,请参阅此答案

回答by lko

A possible solution to this is to read the object from the database, copy the fields to the object, and save it. NHibernate session doesn't know anything about the incoming object which was instantiated by an MVC Model Binder.

一个可能的解决方案是从数据库中读取对象,将字段复制到对象中,然后保存它。NHibernate 会话对由 MVC 模型绑定器实例化的传入对象一无所知。

In certain cases the whole object may not be visible or passed to the View/ViewModel. When saving it should first be read from NHibernate, then updated and saved.

在某些情况下,整个对象可能不可见或传递给 View/ViewModel。保存时应首先从NHibernate中读取,然后更新并保存。

Company cOrig = _companyRepository.Get(company.Id);
cOrig.PropertyToUpdate = company.PropertyToUpdate;
... // Copy the properties to be updated.
// Save the freshly retrieved object! 
// Not the new object coming from the View which NHibernate Session knows nothing about.
_companyRepository.Update(cOrig);

This requires parsing/mapping the ViewModel/Class properties to the Domain Model/Class, but in many cases you don't necessarily present them all to be updated in the view so you would need to do it anyway (Can't save partially empty objects on top of old objects).

这需要将 ViewModel/Class 属性解析/映射到域模型/类,但在许多情况下,您不一定会将它们全部呈现在视图中进行更新,因此无论如何您都需要这样做(无法保存部分为空旧对象之上的对象)。

回答by Ziv.Ti

for more agrgessive way you can use the Clear() method

对于更具侵略性的方式,您可以使用 Clear() 方法

回答by w00ngy

I just encountered this and Claiton Lovato's answer didn't work. However Iko's did work. Here's a little more robust version of Iko's. Downside is x2 trips to the db - one for the Get and another for the insert/update.

我刚刚遇到了这个问题,而 Claiton Lovato 的回答没有用。然而,Iko 确实奏效了。这是 Iko 的一个更强大的版本。缺点是到数据库的 x2 次旅行 - 一次用于获取,另一次用于插入/更新。

A possible solution to this is to read the object from the database, copy the fields to the object, and save it.

一个可能的解决方案是从数据库中读取对象,将字段复制到对象中,然后保存它。

public void Save(Company company)
{

    Company dbCompany = null;
    //update
    if (company.Id != 0)
    {
        dbCompany = _companyRepository.Get(company.Id);
        dbCompany.PropertyToUpdate = company.PropertyToUpdate;
    }
    //insert
    else
    {
        dbDefaultFreightTerm = company;
    }
    // Save either the brand new object as an insert
    // Or update the original dbCompany object with an update
    _companyRepository.SaveOrUpdate(company);
}