从数据库读取时,具有许多关系会导致"Found shared references to a collection"



我是NHIBERNATE的新手,在映射方面遇到麻烦。我未能谷歌找到答案。

我的实体看起来像这样:

public class Triage
{
    public virtual Guid Id { get; set; }
    public virtual IDictionary<int, Discriminator> Discriminators { get; set; }
    // This is to keep FluentNHibernate happy
    public virtual int? SelectedDiscriminatorId { get; set; }
}
public class Discriminator
{
    public virtual int Id { get; set; }
    public virtual int LanguageId { get; set; }
    public override bool Equals(object obj)
    {
        var other = obj as Discriminator;
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Id == other.Id && LanguageId == other.LanguageId;
    }
    public override int GetHashCode()
    {
        return new { Id, LanguageId }.GetHashCode();
    }
}

我的映射看起来像这样:

public class TriageMap : ClassMap<Triage>
{
    public TriageMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        HasMany(x => x.Discriminators)
            .KeyColumn("Id")
            .PropertyRef("SelectedDiscriminatorId")
            .Inverse()
            .Cascade.All()
            .Not.LazyLoad()
            .AsMap(x => x.LanguageId);
        // This mapping is only needed to keep FluentNHibernate happy...
        Map(x => x.SelectedDiscriminatorId);
    }
}
public class DiscriminatorMap : ClassMap<Discriminator>
{
    public DiscriminatorMap()
    {
        CompositeId()
            .KeyProperty(x => x.Id)
            .KeyProperty(x => x.LanguageId);
    }
}

这个想法是,Triage具有选定的歧视器(SelectedDisscriminatorID),并且鉴别式表包含几种可用语言的描述文本。并不特别喜欢Triage所指的构造,它是SelectedDissciminatorID的歧视器,它只是鉴别器(ID和Laganaging ID)中复合密钥的一部分,但这就是我的数据库的外观。

所以当我这样的三叶叶以下时:

_sessionFactory = CreateSessionFactory();
ISession session = _sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
var triages = _sessionFactory
    .GetCurrentSession()
    .Query<Triage>()
    .Fetch(t => t.Discriminators)
    .ToList();
session.Flush();
session.Close();
CurrentSessionContext.Unbind(_sessionFactory);

然后所有工作效果都很好,提供了所选的canciminatorID在被提取的三叶叶中是唯一的。但是,当有几个带有相同选择的歧视剂的三叶叶室时,我会得到一个hibernateException,说"其他信息:找到集合的共享引用:testproject.triage.discisciminators"当它执行session.flush(flush()语句。

时。

知道这里有什么问题,我如何纠正?谢谢。

这就是数据库的外观:

CREATE TABLE [dbo].[Triage](
    [Id] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Triage_Id]  DEFAULT (newid()),
    [SelectedDiscriminatorId] [int] NULL,
 CONSTRAINT [PK_Triage] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Discriminator](
    [ID] [int] NOT NULL,
    [DisplayText] [nvarchar](255) NULL,
    [LanguageID] [int] NOT NULL,
    [Description] [nvarchar](4000) NULL,
 CONSTRAINT [PK_Discriminator] PRIMARY KEY CLUSTERED 
(
    [ID] ASC,
    [LanguageID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

将是一个更卫生的对象模型
public class Triage
{
    public virtual Guid Id { get; set; }
    public virtual Discriminator SelectedDiscriminator { get; set; }
    // left out Equals and GetHashcode
}
public class Discriminator
{
    public Discriminator()
    {
        LocalizedTexts = new Dictionary<int, string>();
    }
    public virtual int Id { get; set; }
    public virtual string Name
    {
        get
        {
            switch (Id)
            {
                case 1:
                    return "Discriminator A";
                case 2:
                    return "Discriminator B";
                case 3:
                    return "Discriminator C";
                default:
                    return "Unknown";
            }
        }
    }
    public virtual IDictionary<int, LocalizedText> LocalizedTexts { get; protected set; }
    public override bool Equals(object obj)
    {
        var other = obj as Discriminator;
        return other != null && (Id == 0 ? ReferenceEquals(this, other) : Id == other.Id);
    }
    public override int GetHashCode()
    {
        return Id;
    }
}
public class LocalizedText
{
    public string DisplayName { get; set; }
    public string Description { get; set; }
}

用映射

public class TriageMap : ClassMap<Triage>
{
    public TriageMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        References(x => x.SelectedDiscriminator, "SelectedDiscriminatorId");
    }
}
public class DiscriminatorMap : ClassMap<Discriminator>
{
    public DiscriminatorMap()
    {
        ReadOnly();
        SchemaExport.None();   // do not create Table for this. usefull for creating Schema for in memory unit-testing
        Table("Discriminators");
        Where("LanguageId = <some value all discriminators have>");
        Id(x => x.Id).GeneratedBy.Assigned();
        HasMany(x => x.LocalizedTexts)
            .Table("Discriminators")
            .KeyColumn("Id")
            .AsMap("LanguageId")
            .Component(c =>
            {
                c.Map(x => x.DisplayName);
                c.Map(x => x.Description);
            })
            .Cascade.AllDeleteOrphan()
            .Not.LazyLoad();
    }
}

唯一的缺点是SQL看起来有些怪异,因为Nhibernate认为歧视者会自己存在。

相关内容

最新更新