【问题标题】:Cannot insert the value NULL into column - NHibernate entity with 2 parents无法将值 NULL 插入列 - 具有 2 个父项的 NHibernate 实体
【发布时间】:2012-10-21 22:39:08
【问题描述】:

{"无法将值 NULL 插入列 'RootID',表 'Legacy.dbo.Middle';列不允许空值。INSERT 失败。\r\n语句已终止。"}

我有一个 Root 类、Middle 类和“底层”类。根类为“中间”作为子级,然后中间有“底部”作为子级。但是,在这个设计不佳的遗留数据库中,“底部”还引用了“根”。

根表

  CREATE TABLE [dbo].[Root](
    [RootID] [int] IDENTITY(1,1) NOT NULL,
    [RootName] [varchar](max) NOT NULL,
 CONSTRAINT [PK_Root] PRIMARY KEY CLUSTERED 
(
    [RootID] 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].[Middle](
        [MiddleID] [int] IDENTITY(1,1) NOT NULL,
        [MiddleName] [varchar](max) NOT NULL,
        [RootID] [int] NOT NULL,
     CONSTRAINT [PK_Middle] PRIMARY KEY CLUSTERED 
    (
        [MiddleID] 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].[Bottom](
        [BottomID] [int] IDENTITY(1,1) NOT NULL,
        [BottomName] [varchar](max) NOT NULL,
        [MiddleID] [int] NOT NULL,
        [RootID] [int] NOT NULL,
     CONSTRAINT [PK_Bottom] PRIMARY KEY CLUSTERED 
    (
        [BottomID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

外键

  ALTER TABLE [dbo].[Middle]  WITH CHECK ADD  CONSTRAINT [FK_Middle_Root] FOREIGN KEY([RootID])
    REFERENCES [dbo].[Root] ([RootID])
    GO

    ALTER TABLE [dbo].[Middle] CHECK CONSTRAINT [FK_Middle_Root]

    ALTER TABLE [dbo].[Bottom]  WITH CHECK ADD  CONSTRAINT [FK_Bottom_Middle] FOREIGN KEY([MiddleID])
    REFERENCES [dbo].[Middle] ([MiddleID])
    GO

    ALTER TABLE [dbo].[Bottom] CHECK CONSTRAINT [FK_Bottom_Middle]
    GO

ALTER TABLE [dbo].[Bottom]  WITH CHECK ADD  CONSTRAINT [FK_Bottom_Root] FOREIGN KEY([RootID])
REFERENCES [dbo].[Root] ([RootID])
GO

ALTER TABLE [dbo].[Bottom] CHECK CONSTRAINT [FK_Bottom_Root]

c#实体

  public class Root
    {
        public Root()
        {
            Middles = new SortedSet<Middle>();
        }

        public int RootID { get; set; }
        public string RootName { get; set; }
        public ISet<Middle> Middles { get; set; }
    }

    public class Middle
    {
        public Middle()
        {
            Bottoms = new SortedSet<Bottom>();
        }

        public int MiddleID { get; set; }
        public Root Root
        {
            get;
            set;
        }

        public string MiddleName { get; set; }
        public ISet<Bottom> Bottoms { get; set; }
    }

    public class Bottom
    {
        public int BottomID { get; set; }
        public Root Root { get; set; }
        public Middle Middle { get; set; }
        public string BottomName { get; set; }
    }

我通过 FluentNHibernate 使用以下映射,但我尝试了很多变体,但无法以任何方式工作。

public class RootMap : IAutoMappingOverride<Root>
{
    public void Override(AutoMapping<Root> mapping)
    {
        mapping.Not.LazyLoad();
        mapping.Id(x => x.RootID);
        mapping.HasMany(x => x.Middles).KeyColumn("RootID").Cascade.AllDeleteOrphan().Inverse();
    }
}

public class MiddleMap : IAutoMappingOverride<Middle>
{
    public void Override(AutoMapping<Middle> mapping)
    {
        mapping.Not.LazyLoad();
        mapping.Id(x => x.MiddleID);
        mapping.References(x => x.Root);
        mapping.HasMany(x => x.Bottoms).KeyColumn("MiddleID").Cascade.AllDeleteOrphan();
    }
}

public class BottomMap : IAutoMappingOverride<Bottom>
{
    public void Override(AutoMapping<Bottom> mapping)
    {
        mapping.Not.LazyLoad();
        mapping.Id(x => x.BottomID);
        mapping.References(x => x.Root);
        mapping.References(x => x.Middle);
    }
}

【问题讨论】:

  • 希望有时间让人们回答这个问题......我想我有一个解决方案,在聚合“根”上使用构造函数和工厂方法

标签: c# nhibernate fluent-nhibernate


【解决方案1】:

您需要将关系的多值方声明为“逆”。见第 6.4 节最后一段:http://nhibernate.info/doc/nh/en/index.html#collections-onetomany

【讨论】:

  • 我试过了,然后我得到'无法将空值插入表 dbo.Bottom 上的列 RootID'。不过我会给你一个+1,因为这是第一次有人解释了'Inverse()'部分并且有意义! :)
  • 您可能还需要在“HasMany(bottoms)”部分使用“inverse”。您还应该在引用上声明 .Not.Nullable()。
  • @OskarBerggren 你说得对,把我从折磨中解救了出来。 '感谢队友。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-05
  • 1970-01-01
  • 2011-05-25
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多