非法企图集合有两个打开的会话功能NHibernate关联 [英] illegal attempt to associate a collection with two open sessions fluent 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屋!