最近我一直在为我的本地项目添加一些功能,而我正在努力解决这一问题。简而言之,NHibernate给了我一句话:
Found shared references to a collection: Page.Menus
简单的部分是,我只想保存将菜单绑定到页面的关系图,您可以在PageMap
中看到下面的参考。我应该补充一点,加载数据效果很好,这是拯救我的行为。
昨天我花了很多时间在这里挖掘,以及好的网络,试图找到答案,我只是一直在罢工。也许这对我来说很糟糕,但我觉得我尝试了一切。如果你知道它在哪里可以提供吗? (感谢)
对于实际细节,我试图简化发生的事情。我添加了PageReposity,UnitOfWork和代理对象,以及它们的映射。
我朦胧的是级联,以及如何保存关系表(多对多)
对于第一部分,这是我保存(添加)时会发生的事情。我实际上是在PageRepository
内完成了这几个方法。由于我对Add()
感到不满,我把它包含在这里:
public override bool Add(Page entity)
{
UnitOfWork.Save(entity);
/* I have also tried doing the following below, which doesn't help
for (var index = 0; index < entity.Menus.Count; index++)
{
UnitOfWork.Save(entity.Menus[index]);
}
*/
UnitOfWork.Commit(); // bam, error!
return true;
}
在UnitOfWork
中我在ctor中设置了以下内容(每次都通过ninject注入ISession,如下所示:
// DomainModule
...
Bind<ISFactory>().To<NHibernateSessionFactory>()
.InSingletonScope()
.WithConstructorArgument("connectionString", _connectWeb);
...
//返回UnitOfWork
...
private ISession Session { get; set; }
...
public UnitOfWork(ISFactory sessionFactory)
{
_sessionFactory = sessionFactory.GetSessionFactory();
Session = _sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Never; // I have also tried FlushMode.Commit
_transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
...
public void Save(object obj)
{
Session.Save(obj);
}
...
public void Commit()
{
if (!_transaction.IsActive)
{
throw new InvalidOperationException("Oops! We don't have an active transaction");
}
try
{
_transaction.Commit();
Session.Flush(); // I did this FlushMode.Never was set
}
catch (Exception exception)
{
_transaction.Rollback();
throw;
}
}
我这里有3节课:
Page
,Menu
和Link
。
public class Page : IEntity<int>
{
public virtual int Id { get; set; }
public virtual IList<Menu> Menus { get; set; }
}
public class Menu : IEntity<int>
{
public virtual int Id { get; set; }
public virtual IList<Link> Links { get; set; }
}
public class Link : IEntity<int>
{
public virtual int Id { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual string Url { get; set; }
}
然后我也有一个映射:
public class PageMap : ClassMap<Page>
{
public PageMap()
{
Id(x => x.Id).GeneratedBy.Native();
HasManyToMany(x => x.Menus)
.Table("MenuToPage")
.ParentKeyColumn("FkPageId")
.ChildKeyColumn("FkMenuId").Cascade.SaveUpdate(); // the cascade is new here just trying to see if it helps
}
}
public class MenuMap : ClassMap<Menu>
{
public MenuMap()
{
Id(x => x.Id); // I had .GeneratedBy.Native(); attached here too.
HasManyToMany(x => x.Links)
.Table("MenuToLinks")
.ChildKeyColumn("FkLinksId")
.ParentKeyColumn("FkMenuId")
.OrderBy("MenuOrder ASC")
.Not.LazyLoad()
.Cascade.None(); // the cascade is new here just trying to see if it helps
}
}
public class LinkMap : ClassMap<Link>
{
public LinkMap()
{
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.Url);
Map(x => x.CreatedDate);
Map(x => x.ModifiedDate);
References(x => x.MetaData, "FkMetaDataId").Not.Nullable().Not.LazyLoad();
}
}
任何人都可以帮助我或指出我的方向,我真的很感谢你的帮助。
总是谢谢你,
凯利
答案 0 :(得分:6)
不幸的是,在保护对象之前,你已经发布了除了对象构造之外的所有内容。
如果将相同的实体集合分配给不同的实例,通常会发生此错误。例如(伪代码)
var menuList = new List<Menu>();...
pageA.Menus = menuList;
pageB.Menus = menuList;
这会将menuList
的引用设置为pageA.Menus
和pageB.Menus
。
相反,将menuList
的所有项目分配给每个页面pageA.AddRange(menuList)
或循环或其他...