对不起,但它是另一个:找到对集合的共享引用

时间:2013-11-30 01:01:42

标签: c#-4.0 nhibernate fluent-nhibernate asp.net-web-api

最近我一直在为我的本地项目添加一些功能,而我正在努力解决这一问题。简而言之,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节课:

PageMenuLink

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();
    }
}

任何人都可以帮助我或指出我的方向,我真的很感谢你的帮助。

总是谢谢你,

凯利

1 个答案:

答案 0 :(得分:6)

不幸的是,在保护对象之前,你已经发布了除了对象构造之外的所有内容。

如果将相同的实体集合分配给不同的实例,通常会发生此错误。例如(伪代码)

var menuList = new List<Menu>();...

pageA.Menus = menuList;
pageB.Menus = menuList;

这会将menuList的引用设置为pageA.MenuspageB.Menus

相反,将menuList的所有项目分配给每个页面pageA.AddRange(menuList)或循环或其他...