【问题标题】:Cannot insert the value NULL into column , table ; column does not allow nulls. INSERT fails无法将值 NULL 插入到列、表中;列不允许空值。插入失败
【发布时间】:2014-06-17 16:01:48
【问题描述】:

我在 SO 上发现了许多类似的问题,我尝试了上述解决方案,但没有一个对我有用,谁能告诉我以下代码有什么问题,需要进行哪些更正才能使其可行:

型号:

public class ParentDataClassData
    {
        public ParentDataClassData()
        {
            TitleSetTitles = new List<ChildDataClass1>();
            TitlesSetEvents = new List<ChildDataClass2>();
        }

        public virtual int TitleSetID { get; set; }
        public virtual string Name { get; set; }
        public virtual IList<ChildDataClass1> TitleSetTitles { get; set; }

        public virtual IEnumerable<ChildDataClass2> TitlesSetEvents { get; set; }

        public virtual object IdentityField
        {
            get { return TitleSetID; }
        }
    }


public class ChildDataClass1
    {
        public ChildDataClass1()
        {
            TitleSet = new ParentDataClassData();
            TitleSetTitleEventMedias = new List<TitleSetTitleEventMediaData>();
        }

        public virtual int TitleSetID
        {
            get { return TitleSet.TitleSetID; }
        }

        public virtual ParentDataClassData TitleSet { get; set; }

        public virtual IList<TitleSetTitleEventMediaData> TitleSetTitleEventMedias { get; set; }

        public virtual object IdentityField
        {
            get { return TitleSetTitleID; }
        }

    }


 public class ChildDataClass2
    {
        public virtual ParentDataClassData TitleSet { get; set;  }

        public virtual int TitleSetEventID
        {
            get;
            set;
        }


        public virtual object IdentityField
        {
            get { return TitleSetEventID; }
        }
    }

映射:

public class ParentDataClassMap : ClassMap<ParentDataEntity>
    {
        public ParentDataClassMap()
        {
            Table("TitleSet");

            LazyLoad();

            Id(x => x.TitleSetID)
                .Column("TitleSetID")
                .GeneratedBy.Native()
                .UnsavedValue(0);


            HasMany(x => x.TitleSetTitles)
            .LazyLoad()
            .Inverse()
            .Fetch.Subselect()
            .Cascade.SaveUpdate()
            .KeyColumn("TitleSetID");

            HasMany(x => x.TitlesSetEvents)
                .LazyLoad()
                .Inverse()
                .Cascade.SaveUpdate()
                .Fetch.Subselect()
                .KeyColumn("TitleSetID");
        }
    }


 public class ChildDataClass1Map : ClassMap<ChildDataClass1>
    {
        public ChildDataClass1Map()
        {
            Table("TitleSetTitle");

            Id(x => x.TitleSetTitleID)
                .Column("TitleSetTitleID")
                .GeneratedBy.Native()
                .UnsavedValue(0);

            References(x => x.TitleSet)
                .Fetch.Join()
                .Not.Nullable()
                .Column("TitleSetID")
                .Cascade.None();


            HasMany(x => x.TitleSetTitleEventMedias)
                .LazyLoad()
                .Inverse()
                .Cascade.AllDeleteOrphan()
                .Fetch.Subselect()
                .KeyColumn("TitleSetTitleID");
        }
}


 public class ChildDataClass2Map : ClassMap<ChildDataClass2>
    {
        public ChildDataClass2Map()
        {
            Table("TitleSetEvent");

            Id(x => x.TitleSetEventID)
                .Column("TitleSetEventID")
                .GeneratedBy.Native()
                .UnsavedValue(0);


            References(x => x.TitleSet)
                .Column("TitleSetID")
                .Not.Update()
                .Not.Insert()
                .Cascade.None();

            Map(x => x.LengthSec).Not.Nullable();
            Map(x => x.EventID).Not.Nullable();

            HasMany(x => x.TitleSetDefaultEventMedia)
                .LazyLoad()
                .Inverse()
                .Cascade.None()
                .Fetch.Join()
                .KeyColumn("TitleSetEventID");

            HasMany(x => x.TitleSetTitleEventMedias)
                .LazyLoad()
                .Inverse()
                .Cascade.None()
                .Fetch.Join()
                .KeyColumn("TitleSetEventID");
        }
    }

测试:

[Test]
        public void CanAddNewTitleSet()
        {
            var titleSet = new TitleSetDataEntity
                {
                    Name = "Somename",
                    ProgramServiceID = 1,
                    CreatedBy = "someuser",
                    CreatedDate = DateTime.Now,
                    ModifiedBy = "someuser",
                    ModifiedDate = DateTime.Now,
                    TitleSetTitles = new List<TitleSetTitleData>
                    {
                        new TitleSetTitleData
                        {
                            IsIncluded = true,
                            IsPremiere = true,
                            TitleTypeCode = "somecode",
                        }
                    },
                    TitlesSetEvents = new List<TitleSetEventData>()
                };


                Session.SaveOrUpdate(titleSet);

            }

并得到异常:

NHibernate.AdoNet.AbstractBatcher:错误 NHibernate.AdoNet.AbstractBatcher [(null)] - 无法执行查询: 插入到 TitleSetTitle ([TitleID], ..., TitleSetID) 值 (@p0, @p1、@p2、@p3、@p4、@p5、@p6、@p7、@p8);选择 SCOPE_IDENTITY() System.Data.SqlClient.SqlException (0x80131904):无法插入 值 NULL 到列“TitleSetID”,表“TitleSetTitle”;柱子 不允许空值。插入失败。声明已终止。

附言

  1. 我在双向映射中使用了逆向
  2. 无论如何 inverse 不服从这些东西,据我了解,它应该首先保存 ParantClassData 以确保 Child 类获得正确的 id。
  3. 不确定,我错过了什么

对上述问题的任何帮助将不胜感激!

更新 添加了更多信息来解释该问题,而不是冗长的代码,我只是想知道是否无论如何TitleSetID readonly 属性相关问题。

【问题讨论】:

  • 停止尝试将空值放入TitleSetID
  • 将代码缩减为显示错误的最小示例。您正在尝试将 NULL 插入到 TitleSetID 中,或者您没有在插入列表中包含 TitleSetID
  • 我没有向TitleSetID 提供任何空值,请参阅我的测试,只是尝试插入新集合。
  • 查看@DanielKelley 的回答。主要问题在于它的描述而不是它的标题

标签: c# sql nhibernate fluent-nhibernate


【解决方案1】:

问题实际上隐藏在这个映射中:

HasMany(x => x.TitleSetTitles)
    ...
    .Inverse();

这个映射正在指导 NHibernate:

孩子会关心这种关系。

但这意味着,那个孩子必须知道它的父母。在这段代码中不是这样:

var titleSet = new TitleSetDataEntity
{
    Name = "Somename",
    ...
    TitleSetTitles = new List<TitleSetTitleData>
    {
        new TitleSetTitleData...
    },
};
session.Save(titleSet);

在这段代码中,new TitleSetTitleData 创建的子实例缺少父引用!这就是问题所在

注意 - 我猜 TitleSetTitles 属性的类型是 IList&lt;ChildDataClass1&gt; TitleSetTitles 但在代码中我们使用 new List&lt;TitleSetTitleData&gt; ...我猜这是一个错字

正确的语法是:

var titleSet = new TitleSetDataEntity
{
    Name = "Somename",
    ...
    TitleSetTitles = new List<TitleSetTitleData>();
};
var child = new TitleSetTitleData
{
    ...
    ParentDataClassData = titleSet,
};
titleSet.TitleSetTitles.Add(child);
session.Save(titleSet);

现在,NHibernate 将拥有足够的信息。 Parent 在列表中添加了 ChildChild 知道 Parent.Inverse() 映射将起作用,因为 Parent 的 ID 不再为空

【讨论】:

  • 这里有模型:对象IdentityField。我无法更改表的架构,因为这是一个旧版应用程序。此外,如果 Table TitleSet 中的 Identity 列,我验证了此列。
  • 我更新了我的答案,它应该清楚地告诉你,我们需要设置父子关系的双方。如果这将被设置,所有的 SQL 语句将被正确处理...
  • 感谢您的帮助,我尝试了但仍然出现同样的错误,我也提到了这个:nanovazquez.com/2013/07/04/… 但不值得,无论如何TitleSetID 每次都是 null 并且只有当我尝试保存 TitleSetTitleSetTitles 这样的孩子,如果没有孩子集合,那么它工作正常,只有当我尝试将它与父母和孩子一起保存时才会发生。
  • 我的测试现在通过了。我正在调查我的实际情况,希望一切都会好起来,我将您的答案标记为 +1,因为您的回答非常有益,我感谢您在这次对话中花费的时间。关于否决我的问题,我不确定,为什么人们不关注实际问题,我相信他们只是阅读问题而不是描述,希望我可以向 SO 的版主提出这个问题,无论如何,你帮了我很多。
  • 干得好,先生!请不要放弃,因为很少有可疑的反对票...享受 NHibernate...出色的工具 ;)
【解决方案2】:

当您尝试将 NULL 值插入列中,或者您忘记在插入语句中包含列时,通常会发生此类错误,因为某些列设置需要数据并且不能留空。确保您在插入语句中包含 TitleSetID 并且您将一个非 NULL 值放入其中。

【讨论】:

  • 我只是想插入集合,看到我的测试TitleSetID 应该自动填充父键,同时我们保存子集合
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2017-10-31
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多