单个Type上的一对多映射,通过代码进行NHibernate映射

时间:2012-08-10 05:46:38

标签: nhibernate

我正在尝试使用此方案的代码映射建立NHibernate映射:

我有一个实体项目,可以包含其他项目的列表。

所以我的项目实体看起来像这样:

public class Project : EntityBase
{
    public Project()
    {
    }

    public virtual string Name { get; set; }
    public virtual string Client { get; set; }
    public virtual string Description { get; set; }

    private readonly IList<Project> _projectLinks = new List<Project>();
    public virtual IList<Project> ProjectLinks
    {
        get { return _projectLinks; }
    }
}

我的数据库表看起来像这样:

CREATE TABLE [dbo].[Project](
[Id] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](255) NOT NULL,
[Description] [nvarchar](MAX) NULL,
[Client] [nvarchar](255) NULL....

CREATE TABLE [dbo].[ProjectLink](
[ProjectId] [uniqueidentifier] NOT NULL,
[LinkedProjectId] [uniqueidentifier] NOT NULL

ProjectId和LinkedProjectId都有外键返回Project.ProjectId

我的映射如下所示:

public class ProjectMapping : ClassMapping<Project>
{
    public ProjectMapping()
    {
        Bag(x => x.ProjectLinks, 
                 collectionMapping =>
                 {
                     collectionMapping.Table("ProjectLink");
                     collectionMapping.Cascade(Cascade.None);
                     collectionMapping.Key(k => k.Column("ProjectId"));
                 },
                 map => map.ManyToMany(p => p.Column("LinkedProjectId")));

这是基于以下帖子的答案:

NHibernate 3.2 many to many mapping by code

这允许我将项目链接添加到我的项目中,当我提交它们时,它们会毫无问题地插入到我的ProjectLinks表中。

问题是当我在插入一个或多个项目之后尝试查询项目的项目链接时,我得到以下异常:

找到了多个具有给定标识符的行:b1fb7034-ee00-4f6a-98d7-35a39a15a0c2,用于类:My.Project

仅当存在给定项目的ProjectLink时才会抛出此异常。上面的Id位于ProjectLink条目的LinkedProjectId列中。如果我添加了N个项目链接,则会始终为ProjectLink表中的第一个LinkedProjectId抛出此异常。

有关如何正确建立此映射的任何想法?

更新

调用_session.Get(_currentRequest.ProjectId).ProjectLinks时会生成以下SQL:

SELECT
    project0_.Id as Id10_5_, project0_.Version as Version10_5_, project0_.Name as Name10_5_, project0_.Client as Client10_5_, project0_.Description as Descript5_10_5_, project0_.ProjectType as ProjectT6_10_5_, project0_.IsSalesTaxApplied as IsSalesT7_10_5_, project0_.SalesTaxRate as SalesTax8_10_5_, project0_.SalesTaxName as SalesTax9_10_5_, project0_.TermsAndConditions as TermsAn10_10_5_, directcost1_.Id as Id3_0_, directcost1_.Version as Version3_0_, directcost1_.ProjectId as ProjectId3_0_, resourcesc2_.Id as Id8_1_, resourcesc2_.Version as Version8_1_, resourcesc2_.ProjectId as ProjectId8_1_, margin3_.Id as Id6_2_, margin3_.Version as Version6_2_, margin3_.OverallMarginPercentage as OverallM3_6_2_, margin3_.CorporateMarginPercentage as Corporat4_6_2_, margin3_.ProvisionalSumsMarginPercentage as Provisio5_6_2_, margin3_.FixedMargin as FixedMar6_6_2_, margin3_.OverallMarginCalculationType as OverallM7_6_2_, margin3_.CorporateMarginCalculationType as Corporat8_6_2_, project4_.Id as Id10_3_, project4_.Version as Version10_3_, project4_.Name as Name10_3_, project4_.Client as Client10_3_, project4_.Description as Descript5_10_3_, project4_.ProjectType as ProjectT6_10_3_, project4_.IsSalesTaxApplied as IsSalesT7_10_3_, project4_.SalesTaxRate as SalesTax8_10_3_, project4_.SalesTaxName as SalesTax9_10_3_, project4_.TermsAndConditions as TermsAn10_10_3_, spreadopti5_.Id as Id12_4_, spreadopti5_.Version as Version12_4_, spreadopti5_.AlwaysRoundupSellRates as AlwaysRo3_12_4_
FROM
    Project project0_
    left outer join CostSchedule directcost1_ on project0_.Id=directcost1_.ProjectId and directcost1_.Discriminator=''DCS''
    left outer join ResourceSchedule resourcesc2_ on project0_.Id=resourcesc2_.ProjectId
    left outer join Margin margin3_ on project0_.Id=margin3_.Id
    left outer join Project project4_ on margin3_.Id=project4_.Id
    left outer join SpreadOptions spreadopti5_ on project4_.Id=spreadopti5_.Id
WHERE
    project0_.Id=@p0',N'@p0 uniqueidentifier',@p0='0F91D16E-0D35-444C-93FF-C0C696C7BE58'

一起
SELECT
    projectlin0_.ProjectId as ProjectId6_, projectlin0_.LinkedProjectId as LinkedPr2_6_, project1_.Id as Id10_0_, project1_.Version as Version10_0_, project1_.Name as Name10_0_, project1_.Client as Client10_0_, project1_.Description as Descript5_10_0_, project1_.ProjectType as ProjectT6_10_0_, project1_.IsSalesTaxApplied as IsSalesT7_10_0_, project1_.SalesTaxRate as SalesTax8_10_0_, project1_.SalesTaxName as SalesTax9_10_0_, project1_.TermsAndConditions as TermsAn10_10_0_, directcost2_.Id as Id3_1_, directcost2_.Version as Version3_1_, directcost2_.ProjectId as ProjectId3_1_, resourcesc3_.Id as Id8_2_, resourcesc3_.Version as Version8_2_, resourcesc3_.ProjectId as ProjectId8_2_, margin4_.Id as Id6_3_, margin4_.Version as Version6_3_, margin4_.OverallMarginPercentage as OverallM3_6_3_, margin4_.CorporateMarginPercentage as Corporat4_6_3_, margin4_.ProvisionalSumsMarginPercentage as Provisio5_6_3_, margin4_.FixedMargin as FixedMar6_6_3_, margin4_.OverallMarginCalculationType as OverallM7_6_3_, margin4_.CorporateMarginCalculationType as Corporat8_6_3_, project5_.Id as Id10_4_, project5_.Version as Version10_4_, project5_.Name as Name10_4_, project5_.Client as Client10_4_, project5_.Description as Descript5_10_4_, project5_.ProjectType as ProjectT6_10_4_, project5_.IsSalesTaxApplied as IsSalesT7_10_4_, project5_.SalesTaxRate as SalesTax8_10_4_, project5_.SalesTaxName as SalesTax9_10_4_, project5_.TermsAndConditions as TermsAn10_10_4_, spreadopti6_.Id as Id12_5_, spreadopti6_.Version as Version12_5_, spreadopti6_.AlwaysRoundupSellRates as AlwaysRo3_12_5_
FROM
    ProjectLink projectlin0_
    left outer join Project project1_ on projectlin0_.LinkedProjectId=project1_.Id
    left outer join CostSchedule directcost2_ on project1_.Id=directcost2_.ProjectId and directcost2_.Discriminator=''DCS''
    left outer join ResourceSchedule resourcesc3_ on project1_.Id=resourcesc3_.ProjectId
    left outer join Margin margin4_ on project1_.Id=margin4_.Id
    left outer join Project project5_ on margin4_.Id=project5_.Id
    left outer join SpreadOptions spreadopti6_ on project5_.Id=spreadopti6_.Id
WHERE
    projectlin0_.ProjectId=@p0',N'@p0 uniqueidentifier',@p0='0F91D16E-0D35-444C-93FF-C0C696C7BE58'

我曾试图保持示例简单,上面生成的SQL来自完整的Project实体。

1 个答案:

答案 0 :(得分:0)

我的猜测是,外连接会产生多个结果,这会混淆许多初始化。尝试延迟加载计划,保证金以验证