Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正确地在nHibernate中实现双向多对多_C#_C# 4.0_Nhibernate_Fluent Nhibernate - Fatal编程技术网

C# 如何正确地在nHibernate中实现双向多对多

C# 如何正确地在nHibernate中实现双向多对多,c#,c#-4.0,nhibernate,fluent-nhibernate,C#,C# 4.0,Nhibernate,Fluent Nhibernate,我正试图了解如何在Dotnet4.5中正确使用NHibernate中的多对多关系。要使用的集合类型以及初始化它们的方式 场景:对单位和位置进行建模。与下表存在多对多关系: 组织单位 位置 组织单位职位 我使用双向设置器,因此无论我选择orgUnit.AddPosition(position)还是position.AddOrgUnit(orgUnit),都应该将关系添加到这两个集合中 下面是我的示例代码 public class Position { public Pos

我正试图了解如何在Dotnet4.5中正确使用NHibernate中的多对多关系。要使用的集合类型以及初始化它们的方式

场景:对单位和位置进行建模。与下表存在多对多关系:

组织单位 位置 组织单位职位

我使用双向设置器,因此无论我选择orgUnit.AddPosition(position)还是position.AddOrgUnit(orgUnit),都应该将关系添加到这两个集合中

下面是我的示例代码

public class Position 
    {
        public Position()
        {
            OrgUnits = new List<OrgUnit>(); 
        }

        public virtual ICollection<OrgUnit> OrgUnits { get; set; }

        public virtual void AddOrgUnit(OrgUnit orgUnit)
        {
            if (!OrgUnits.Contains(orgUnit))
            {
                OrgUnits.Add(orgUnit);
                if (!orgUnit.Positions.Contains(this))
                    orgUnit.AddPosition(this);
            }
        }


        public class PositionMap : ClassMap<Position>
        {
            public PositionMap()
            {
                    HasManyToMany(x => x.OrgUnits)
                    .ChildKeyColumn("OrgUnitID")
                    .ParentKeyColumn("PositionID")
                    .Table("OrgUnitPositions")
                    .Fetch.Select()
                    .Cascade.AllDeleteOrphan()
                    .AsBag()
                    .Inverse();
            }

        }

        public class OrgUnit
        {
            public OrgUnit()
            {
                Positions = new HashSet<Position>();
            }

            public virtual ICollection<Position> Positions { get; set; }

            public virtual void AddPosition(Position value)
            {
                if (!Positions.Contains(value))
                {
                    Positions.Add(value);
                    if (!value.OrgUnits.Contains(this))
                        value.AddOrgUnit(this);
                }
            }
        }
        public class OrgUnitMap : ClassMap<OrgUnit>
        {
        public OrgUnitMap()
        {
            HasManyToMany(x => x.Positions)
            .ChildKeyColumn("PositionID")
            .ParentKeyColumn("OrgUnitID")
            .Table("OrgUnitPositions")
            .Fetch.Select()
            .Cascade.AllDeleteOrphan()
            .AsSet()
            ;
        }
    }
下面是我的发现-请记住orgUnit.positions只包含1项,而for each只是为了在调试器中访问该项

ReferenceEquals(p,this)false

p、 GetHashCode()40148707

这个.GetHashCode()53416668

this.ID{8386857d-a52e-4f17-8094-a231003299b5}

p、 ID{8386857d-a52e-4f17-8094-a231003299b5}

p、 说明“鲍勃”

此.Description“bob”

p、 description=“Jane”

此.Description“Jane”

p、 说明“简”

这是奇怪的一个!hashcode是不同的,但它似乎是同一对象的同一实例。也就是说,如果我在“this”版本中更改属性,它在“p”版本中也会更改

最后,, ReferenceEquals(p.ReportsToPosition,this.ReportsToPosition)true

哪个倾向于表明它们来自同一个hibernate会话?(即父母是一样的)


这是我的调用代码,我们为IoC使用StrctureMap,将ISession注入到repos中。我已将代码更改为传入BLL,这保证了相同的Isession,因为存储库被注入其中

奇怪的是,导致错误的唯一一行就是所示的那一行,如果我删除上面的行,它也可以完美地工作

[TestMethod]
    public void CreateExampleOrgStructure()
    {
        OrgStructureLogic osl = (OrgStructureLogic)ObjectFactory.GetInstance(typeof(OrgStructureLogic));
        Domain domain = osl.GetNewDomain(DomainTypeEnum.ReportingLines);
        domain.Name = string.Format("blah.Net - {0} {1}", DateTime.Now.ToLongDateString(), DateTime.Now.ToLongTimeString());

        OrgUnit ouGlobal = domain.RootOrgUnit;
        ouGlobal.Name = "Global";

        OrgUnit ouTech = GetNewOrgUnit(ouGlobal, "Technology", osl);
        AddPositionToOrgUnit(ouTech, "Chief Technology Officer", osl);
        AddPositionToOrgUnit(ouTech, "General Manager Technology", osl);

        OrgUnit ouFeatureDevelopers = GetNewOrgUnit(ouTech, "Feature Dev", osl);
        AddPositionToOrgUnit(ouFeatureDevelopers, "Senior Feature Developer", osl);
        AddPositionToOrgUnit(ouFeatureDevelopers, "Feature Developer", osl);

        OrgUnit ouSupportDevelopers = GetNewOrgUnit(ouTech, "Support Dev", osl);
        AddPositionToOrgUnit(ouSupportDevelopers, "Senior Support Developer", osl);
        AddPositionToOrgUnit(ouSupportDevelopers, "Support Developer", osl);

        OrgUnit ouDevManagement = GetNewOrgUnit(ouTech, "Management", osl);
        AddPositionToOrgUnit(ouDevManagement, "Dev Manager", osl); /* This is the problem!!!!*/
        AddPositionToOrgUnit(ouDevManagement, "Application Architect", osl);

        osl.SaveDomain(domain);
    }
更奇怪的是,我也可以解决这个问题

private void AddPositionToOrgUnit(OrgUnit orgUnit, string positionName, OrgStructureLogic osl)
    {
        orgUnit.AddPosition(GetPositionByName(positionName), osl);
    }


在堆栈跟踪之后,GetHashCode的值在此处发生更改:

if (!position.OrgUnits.Contains(this))
{
    position.AddOrgUnit(this);
}
例如,position.GetHashCode()=“a”,但当我进入position.AddOrgUnit时,这个.GetHashCode()是“b”

查看堆栈跟踪

[Native to Managed Transition]      NHibernate.dll!NHibernate.Proxy.DefaultLazyInitializer.Intercept(NHibernate.Proxy.DynamicProxy.InvocationInfo info = {NHibernate.Proxy.DynamicProxy.InvocationInfo}) + 0x14d bytes  
PositionProxyModule.mod!PositionProxy.AddOrgUnit() + 0x1f2 bytes    

看来nHibernate代理正在成为阻碍。因此–sl3dg3是正确的,解决方案是覆盖Equals&GetHashCode。

您是否尝试过比较实体的ID而不是引用?我以前遇到过这种问题,尤其是当NHibernate生成代理类时。有时我会覆盖比较实体ID的
Equals
(和
GetHashCode
)代码。您能在调用
orgUnit.AddPosition(position)
的地方显示代码吗?我猜
orgUnit
position
来自两个不同的NHibernate会话。当您在调试器中看到它时,是否可以检查您认为相等的两个实例是否实际执行了
ReferenceEquals
?@sl3dg3我添加了ID比较的结果-它们是相同的。我在覆盖Equals/GetHashCode时犹豫不决,因为我喜欢创建空对象的图形,然后通过调用save(rootObject)-ie保存它们,我希望能够在对象ID为空时进行比较。我已尝试将集合更改为IESI集合,并且具有相同的IDproblem@DanielSchilling-我修改了代码,通过BLL引用了我的回购协议-所以我不认为这是一个不同的iSession。
if (!position.OrgUnits.Contains(this))
{
    position.AddOrgUnit(this);
}
[Native to Managed Transition]      NHibernate.dll!NHibernate.Proxy.DefaultLazyInitializer.Intercept(NHibernate.Proxy.DynamicProxy.InvocationInfo info = {NHibernate.Proxy.DynamicProxy.InvocationInfo}) + 0x14d bytes  
PositionProxyModule.mod!PositionProxy.AddOrgUnit() + 0x1f2 bytes