not-null 属性 references a null or transient value - 对Inverse和Cascade的理解

not-null property references a null or transient value - understanding of Inverse and Cascade

This is fragment of my database project, and this 是 Fl​​uent NHibernate

自动生成的数据库片段

这些是我在上述数据库项目的 Fluent NHibernate 中的实体和映射 类。

实体:

public class BaseEntity<T> where T : BaseEntity<T> {
    public virtual int Id { get; set; }
...
}

public class Person<T> : BaseEntity<T> where T : BaseEntity<T> {
    public virtual string FirstName { get; set; }
    public virtual string SecondName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string PESEL { get; set; }
    public virtual DateTime BirthDate { get; set; }
    public virtual string City { get; set; }
    public virtual string PostalCode { get; set; }
    public virtual string Street { get; set; }
    public virtual string HouseNr { get; set; }
    public virtual string ApartmentNr { get; set; }
    public virtual string PhoneNr { get; set; }
    public virtual string Email { get; set; }
}

public class DrivingLicense : BaseEntity<DrivingLicense> {
    #region Relations
    public virtual IList<DrivingLicensePermissions> DrivingLicensePermissions { get; set; }
    public virtual Student Student { get; set; }
    #endregion

    public virtual DateTime IssueDate { get; set; }
    public virtual string DrivingLicenseNr { get; set; }
}

public class DrivingLicensePermissions : BaseEntity<DrivingLicensePermissions> {
    #region Relations
    public virtual DrivingLicense DrivingLicense { get; set; }
    #endregion

    public virtual DrivingLicenseCategory Category { get; set; }
}

映射:

class StudentMap : ClassMap<Student> {
    public StudentMap() {
        Id(x => x.Id);
        Map(x => x.FirstName).Not.Nullable().Length(25);
        Map(x => x.SecondName).Nullable().Length(25);
        Map(x => x.LastName).Not.Nullable().Length(50);
        Map(x => x.PESEL).Nullable().Length(11);
        Map(x => x.BirthDate).Not.Nullable();
        Map(x => x.City).Not.Nullable().Length(50);
        Map(x => x.PostalCode).Nullable().Length(6);
        Map(x => x.Street).Not.Nullable().Length(50);
        Map(x => x.HouseNr).Not.Nullable().Length(10);
        Map(x => x.ApartmentNr).Nullable().Length(10);
        Map(x => x.PhoneNr).Nullable().Length(20);
        Map(x => x.Email).Nullable().Length(100);

        References(x => x.DrivingLicense).Nullable().Cascade.All();
        References(x => x.User).Nullable().Cascade.All();
        HasMany(x => x.Participants).Cascade.All();
    }
}

class DrivingLicenseMap : ClassMap<DrivingLicense> {
    public DrivingLicenseMap() {
        Id(x => x.Id);
        Map(x => x.IssueDate).Not.Nullable();
        Map(x => x.DrivingLicenseNr).Not.Nullable().Length(20);

        HasMany(x => x.DrivingLicensePermissions).Cascade.All();
        References(x => x.Student).Not.Nullable();
    }
}

class DrivingLicensePermissionsMap : ClassMap<DrivingLicensePermissions> {
    public DrivingLicensePermissionsMap() {
        Id(x => x.Id);
        Map(x => x.Category).Not.Nullable();

        References(x => x.DrivingLicense).Not.Nullable();
    }
}

我的问题是这个异常:not-null 属性 引用了空值或瞬态值 Model.Entities.DrivingLicense.Student, 当我试图像这样

坚持学生对象时
session.Save(student);

已将 DrivingLicense 对象分配给它的 DrivingLicense 属性。

我认为这是由于错误的映射引起的 - 错误的级联或缺少逆。我尝试了很多组合,但无法正常工作。 Student table 有 DrivingLicense_id 而相反,DrivingLicense 有 Student_id 列是否正确?!

这个问题的关键是 DrivingLicense 通过 Not.Nullable() 映射引用了 Student。这意味着当 NH 试图持久化 DrivingLicense 时,它是 Student 属性 不能是 null.

调试代码并在 Save(student) 调用处暂停。检查对象图,查看 studentDrivingLicense 属性 及其 Student 属性。我的猜测是 null.

您需要检查映射的 Not.Nullable() 方面或确保您的对象图正确 'wired',然后再坚持。

为了解决我的问题,我不得不将 Reference-to-Reference 更改为 HasOne-to-Reference。

现在看起来像这样。

实体没有改变

映射:

class StudentMap : ClassMap<Student> {
    public StudentMap() {
        Id(x => x.Id);
        Map(x => x.FirstName).Not.Nullable().Length(25);
        Map(x => x.SecondName).Nullable().Length(25);
        Map(x => x.LastName).Not.Nullable().Length(50);
        Map(x => x.PESEL).Nullable().Length(11);
        Map(x => x.BirthDate).Not.Nullable();
        Map(x => x.City).Not.Nullable().Length(50);
        Map(x => x.PostalCode).Nullable().Length(6);
        Map(x => x.Street).Not.Nullable().Length(50);
        Map(x => x.HouseNr).Not.Nullable().Length(10);
        Map(x => x.ApartmentNr).Nullable().Length(10);
        Map(x => x.PhoneNr).Nullable().Length(20);
        Map(x => x.Email).Nullable().Length(100);

        HasOne(x => x.DrivingLicense).PropertyRef(x => x.Student).Cascade.All();
        References(x => x.User).Unique().Not.Nullable();
        HasMany(x => x.Participants).Cascade.All();
    }
}

class DrivingLicenseMap : ClassMap<DrivingLicense> {
    public DrivingLicenseMap() {
        Id(x => x.Id);
        Map(x => x.IssueDate).Not.Nullable();
        Map(x => x.DrivingLicenseNr).Not.Nullable().Length(20);

        HasMany(x => x.DrivingLicensePermissions).Cascade.All();
        References(x => x.Student).Unique().Not.Nullable();
    }
}

class DrivingLicensePermissionsMap : ClassMap<DrivingLicensePermissions> {
    public DrivingLicensePermissionsMap() {
        Id(x => x.Id);
        Map(x => x.Category).Not.Nullable();

        References(x => x.DrivingLicense).Nullable();
    }
}

感谢这一变化,循环引用消失了。 see it here

Students table 中没有 DrivingLicense_id,现在我可以像以前一样保存 Student 实体和 DrivingLicense,它是权限。

session.Save(student);