fluentnhibernate有许多相同标识符异常
我有一个多对多的关系,两个对象之间的应用程序,查询。我已经构建了在两个对象映射中都有HasManyToMany映射的映射 第一次使用SaveOrUpdate应用程序时,它工作正常,并且条目正确地放置在联接表中 但是,第二次使用它时,我得到了错误:“具有相同标识符的不同对象已与会话关联” 异常在下面显示的addQuery代码的最后几行抛出 这里是实体和地图。如有任何建议,将不胜感激fluentnhibernate有许多相同标识符异常,nhibernate,fluent-nhibernate,fluent-nhibernate-mapping,Nhibernate,Fluent Nhibernate,Fluent Nhibernate Mapping,我有一个多对多的关系,两个对象之间的应用程序,查询。我已经构建了在两个对象映射中都有HasManyToMany映射的映射 第一次使用SaveOrUpdate应用程序时,它工作正常,并且条目正确地放置在联接表中 但是,第二次使用它时,我得到了错误:“具有相同标识符的不同对象已与会话关联” 异常在下面显示的addQuery代码的最后几行抛出 这里是实体和地图。如有任何建议,将不胜感激 public class Application { public virtual int id { get
public class Application
{
public virtual int id { get; set; }
public virtual string name { get; set; }
public virtual IList<Query> queries { get; set; }
public Application()
{
this.queries = new List<Query>();
}
public virtual void AddQuery(Query qry)
{
qry.applicationsUsedIn.Add(this);
queries.Add(qry);
}
}
更新代码以防它帮助其他人
这里的问题隐藏在许多打开的会话中,实际上是一个操作。这不是执行此插入/更新的正确方式。我们应该始终将一组相互依赖的操作打包到一个会话、一个事务中 发生的情况是,我们收到的查询如下:
Query qry = getQuery(appname, qryname);
我们有一个对象,它是会话的一部分,刚刚超出范围。qry实例现在已完全填充,因为
它是从数据库加载的现有对象。。。
查看映射时使用的IList应用程序集合的映射为.Not.LazyLoad
对于其他Not.LazyLoad映射也是如此。。。
所以一旦我们进入最后一个事务和它自己的会话。。。我们的物体可能会被大量填充。。。与上次会话中加载的对象具有相同的ID
要快速解决此问题,请执行以下操作:
在操作开始时打开会话
在开始时打开事务
如果有新对象,请仅调用Save
对于通过getQuery检索的对象,在同一会话中运行的getApplication不调用SaveOrUpdate。它们已经在会话中,这就是本例中SaveOrUpdated将它们放在会话中的主要原因
调用transaction.Commit,所有内容都将正确持久化
b在操作结束时关闭会话
注意:我将更改多对多的映射
卸下Not.LazyLoad。懒惰是我们最想要的。。
删除级联,因为它与另一端有关,而与配对表无关。如果这是有意的,那就别管它
我真的很感谢你在这方面的帮助。我做了你建议的改变,还有更多。基本上,我将函数中的所有代码,以及它们自己的会话中的所有代码移到了同一个会话中。如果这有帮助的话,那就太好了。享受NHibernate。。。很好,是的。我希望有一种方法可以将代码分解成函数以供重用,但这实际上使代码更具可读性。Radim,有没有一种方法可以将对象应用程序、会话外的查询保存到另一个会话中以供重用?我知道,通常我会说,我们应该在操作中考虑。有些人在写。。。有些人阅读。它们可以代表一个工作单元。因此,我的做法是,例如,在web中打开请求的会话。。。执行需要的操作,在结束时提交或回滚并关闭会话。在网络之外的其他世界中,我们可以拥有所谓的分离对象。它们必须稍后合并到其他/下一个会话中。请检查:感谢共享更新!干得好
public class ApplicationMap : ClassMap<Application>
{
public ApplicationMap()
{
Table("dbo.Applications");
Id(x => x.id).Column("id");
Map(x => x.name).Column("name");
HasManyToMany(x => x.queries)
.Table("dbo.ApplicationsQueries")
.ParentKeyColumn("appid")
.ChildKeyColumn("qryid")
.Not.LazyLoad()
.Cascade.SaveUpdate();
}
}
public class QueryMap : ClassMap<Query>
{
public QueryMap()
{
Table("dbo.Queries");
Id(x => x.id);
Map(x => x.name);
Map(x => x.query);
HasMany(x => x.parameters)
.Cascade.All()
.Inverse();
HasManyToMany(x => x.applicationsUsedIn)
.Table("dbo.ApplicationsQueries")
.ParentKeyColumn("qryid")
.ChildKeyColumn("appid")
.Inverse()
.Cascade.SaveUpdate()
.Not.LazyLoad();
}
}
public void addQuery(string appname, string qryname, string qrystr)
{
Application app = getApplication(appname);
if (null == app)
{
app = addApplication(appname);
}
Query qry = getQuery(appname, qryname);
if (null == qry)
{
using (ISessionFactory isf = getSessionFactory())
{
using (var sess = isf.OpenSession())
{
using (var tran = sess.Transaction)
{
tran.Begin();
qry = new Query();
qry.name = qryname;
qry.query = qrystr;
sess.Save(qry);
tran.Commit();
}
}
}
}
if (!app.queries.Contains(qry))
{
using (ISessionFactory isf = getSessionFactory())
{
using (var sess = isf.OpenSession())
{
using (var tran = sess.Transaction)
{
tran.Begin();
app.AddQuery(qry);
//This is where the exception is thrown
sess.SaveOrUpdate(app);
tran.Commit();
}
}
}
}
}
public ApplicationMap()
{
Table("dbo.Applications");
Id(x => x.id).Column("id");
Map(x => x.name).Column("name");
HasManyToMany(x => x.queries)
.Table("dbo.ApplicationsQueries")
.ParentKeyColumn("appid")
.ChildKeyColumn("qryid")
.LazyLoad();
}
public QueryMap()
{
Table("dbo.Queries");
Id(x => x.id);
Map(x => x.name);
Map(x => x.query);
HasMany(x => x.parameters)
.Cascade.All()
.Inverse();
HasManyToMany(x => x.applicationsUsedIn)
.Table("dbo.ApplicationsQueries")
.ParentKeyColumn("qryid")
.ChildKeyColumn("appid")
.Inverse()
.LazyLoad();
}
public void addQuery(string appname, string qryname, string qrystr)
{
using (ISessionFactory isf = getSessionFactory())
{
using (var sess = isf.OpenSession())
{
using (var tran = sess.Transaction)
{
tran.Begin();
var critapp = sess.CreateCriteria<Application>()
.Add(Restrictions.Eq("name", appname));
Application app = (Application)critapp.UniqueResult();
if (null == app)
{
app = new Application();
app.name = appname;
sess.Save(app);
}
var critqry = sess.CreateCriteria<Query>()
.Add(Restrictions.Eq("name", qryname));
Query qry = (Query)critqry.UniqueResult();
if (null == qry)
{
qry = new Query();
qry.name = qryname;
qry.query = qrystr;
sess.Save(qry);
}
if (!app.queries.Contains(qry))
{
app.AddQuery(qry);
}
tran.Commit();
}
}
}
}
Query qry = getQuery(appname, qryname);