非法企图集合有两个打开的会话功能NHibernate关联 [英] illegal attempt to associate a collection with two open sessions fluent nhibernate

查看:142
本文介绍了非法企图集合有两个打开的会话功能NHibernate关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的例外的非法企图集合有两个打开的会话关联,它提出了每一个我救实体包含儿童的收集时间。
我google一下。我发现我打电话时保存打开两个或两个以上的会议,但我敢肯定,我只使用一个会话。
我哪里做错了?我怎样才能解决这个problemn?
注:我使用MVC4,流畅的NHibernate

I have this exception "illegal attempt to associate a collection with two open sessions", it raises every time I save entity contains collection of children. I google it. I found that I opened two or more sessions when calling save, but I'm sure that I'm using only one session. Where I did wrong? How can I solve this problemn? Note: I'm using MVC4, and fluent NHibernate.

实体:

public class Employee : EntityBase<int>
{
    public Employee()
        : base()
    {
        Phones = new List<Phone>();
    }

    public Employee(int id) : this() { Id = id; }
    [Browsable(false)]
    public override ApprovalBase Approval
    {
        get;
        set;
    }

    public virtual string Name { get; set; }
    public virtual string Job { get; set; }

    [Browsable(false)]
    public virtual IList<Phone> Phones { get; set; }
}
public class Phone : EntityBase<int>
{
    public Phone()
        : base()
    {
    }
    public Phone(int id) : this() { Id = id; }
    public override ApprovalBase Approval
    {
        get;
        set;
    }

    public virtual string PhoneNumber { get; set; }
    public virtual string PhoneType { get; set; }
    public virtual int EmployeeId { get; set; }

    public virtual Employee Employee { get; set; }
}

映射:

public sealed class EmployeeMap : ClassMap<Employee>
{
    public EmployeeMap()
    {
        Table("dbo.Employee");

        Id(x => x.Id).Column("EmployeeId");
        Map(x => x.Name);
        Map(x => x.Job);
        HasMany(x => x.Phones).KeyColumn("EmployeeId").Table("dbo.Phone").Cascade.All().Inverse();
    }
}
public sealed class PhoneMap : ClassMap<Phone>
{
    public PhoneMap()
    {
        Table("dbo.Phone");
        Id(x => x.Id).Column("PhoneId");
        Map(x => x.PhoneNumber);
        Map(x => x.PhoneType);
        Map(x => x.EmployeeId);
        References(x => x.Employee).Column("EmployeeId")
            .Not.Update()
            .Not.Insert();
    }
}

存储库:

public abstract class RepositoryBase<TEntity, TIdentity>
    : IRepository<TEntity, TIdentity>
    where TEntity : EntityBase<TIdentity>
    where TIdentity : IComparable
{
    private readonly IPersistor<TEntity, TIdentity> persistor; //contains the session to operate with the database
    public IPersistor<TEntity, TIdentity> Persistor { get { return persistor; } }

    private readonly IFinder<TEntity, TIdentity> finder;
    public IFinder<TEntity, TIdentity> Finder { get { return finder; } }

    private RepositoryBase() { }

    public RepositoryBase(
        IPersistor<TEntity, TIdentity> persistor,
        IFinder<TEntity, TIdentity> finder)
    {
        this.persistor = persistor;
        this.finder = finder;
        this.finder.DataSource = Query();
    }

    // Get entity by ID
    public virtual TEntity Get(TIdentity id)
    {
        return persistor.Get(id);
    }

    /// <summary>
    /// Validate and Save the entity. If the validation failed, will not save the entity,
    /// but returns back list of error messages.
    /// </summary>
    public virtual IList<String> Save(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentNullException("entity");

        IList<String> errors = entity.Validate();

        if (errors.Count == 0)
        {
            persistor.Save(entity);
        }

        return errors;
    }

    // Delete entity from persistance repository
    public virtual void Delete(TIdentity id)
    {
        persistor.Delete(id);
    }

    /// Gets IQueryable which we use from the concrete
    /// implementation of repository to implement our 
    /// query methods (FindBy).
    protected IQueryable<TEntity> Query()
    {
        return persistor.Query();
    }

    public IList<TEntity> GetAll()
    {
        return persistor.Query().ToList();
    }
}

public class EmployeeRepository : RepositoryBase<Employee, int>, IEmployeeRepository
{
    public EmployeeRepository(
        IPersistor<Employee, int> persistor,
        IEmployeeFinder entityFinder)
        : base(persistor, entityFinder) { }

    public IEmployeeFinder Find
    {
        get { return (IEmployeeFinder)Finder; }
    }
}
public class PhoneRepository : RepositoryBase<Phone, int>, IPhoneRepository
{
    public PhoneRepository(
        IPersistor<Phone, int> persistor,
        IPhoneFinder entityFinder)
        : base(persistor, entityFinder) { }

    public IPhoneFinder Find
    {
        get { return (IPhoneFinder)Finder; }
    }
}

在我填的是员工的所有信息,并添加电话的收集,当我preSS保存的信息尚未保存在数据库中。一些调试后,我发现,当我的程序达到Session.SaveOrUpdate(实体);上面的例外出现。
如何解决这个问题?

After I fill all the information of the Employee and add collection of phones, when I press save, the information haven't been saved in the database. After some debugging, I found that when my program reaches to "Session.SaveOrUpdate(entity);" the exception above appeared. How to solve this issue?

推荐答案

此外,对于完整性,通常有两种类型的问题。

Also, for completeness, there are usually two type of issues.

1)常见的,涉及到管理不当DAO对象 - 用自己的ISession创建:

1) common, related to not properly managed DAO objects - with their own ISession creation:

作为例子在上面定义的 - 有可能是在游戏中的两个对象与存储库的工作:1。 persistor 2 取景器

As in example defined above - there could be two objects in play to work with the repository: 1. persistor and 2 finder.

他们俩确实有的Isession ,其自身的一个实例。如果取景器并取得成功,并发现一些信息如的电话的...实体员工 assing他们,并试图保存...但是:电话的里面有一个不同会话(实例),然后的员工的。

They both do have an instance of ISession, its own. If finder does succeed and finds something... e.g. Phones ... the entity Employee assing them and tries to Save ... but: Phones are inside a different session (instance) then Employee.

2)经常与ASP.NET MVC和它的重定向()作用的结果:

2) very often related to ASP.NET MVC and its Redirect() action results:

最有可能的电话的是由不同的会话加载。不是由一个,这是目前的当前的 - 的其中之一不处理的雇员的。

Most likely Phones were loaded by a different session. Not by the one, which is at the moment the "current" - the one which does process the Employee.

因此​​,最可疑的是呼叫重定向。如果是,什么情况是,我们的一个控制器续航时间加载对象 - 把它放进温度字典 - 通话的重定向其他控制器 - 现在有新会与旧会话相关联和老年对象(休市)。

So the most suspected is the call Redirect. If yes, what happens is that we load an object in one controller life time - put it into Temp dictionary - call Redirect to other controller - and now there is new session and older object associated with older session (closed one).

解决方案:确保,所有的DAO处理是一个范围的Isession一部分。会议中的没有传送任何数据(也不控制器重定向中) ...

Solution: Be sure, that all the DAO handling is part of one ISession scope. Do not transfer any data among sessions (nor among controller redirections)...

这篇关于非法企图集合有两个打开的会话功能NHibernate关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆