NHibernate,通过父对象添加子对象,而不是在子对象上设置对父对象的引用

NHibernate,通过父对象添加子对象,而不是在子对象上设置对父对象的引用,nhibernate,fluent-nhibernate,nhibernate-mapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,我目前正在进行我的第一个NHibernate项目 为了测试它,我正在构建一个实体图,并尝试将该图持久化到数据库中。当我通过IList上的add将子项添加到父项时,insert在数据库中不起作用,因为我在数据库中得到null列异常(代码段1) 当我将子对象上的引用设置为父对象时,它正在工作(尽管这对我来说并不自然,请参见代码片段) 这是正常的行为还是我做错了什么 片段1: var country = new Country(); var countryLocale = new CountryLoc

我目前正在进行我的第一个NHibernate项目

为了测试它,我正在构建一个实体图,并尝试将该图持久化到数据库中。当我通过IList上的add将子项添加到父项时,insert在数据库中不起作用,因为我在数据库中得到null列异常(代码段1)

  • 当我将子对象上的引用设置为父对象时,它正在工作(尽管这对我来说并不自然,请参见代码片段)
  • 这是正常的行为还是我做错了什么
  • 片段1:

    var country = new Country();
    var countryLocale = new CountryLocale { LangCode = "nl-nl", Name = "Nederland" };
    country.CountryLocales.Add(countryLocale);
    
    var city = new City();
    var cityLocale = new CityLocale { LangCode = "nl-nl", Name = "Amsterdam" };
    city.CityLocales.Add(cityLocale);
    country.Cities.Add(city);
    
    var country = new Country();
    
    var countryLocale = new CountryLocale { Country = country,LangCode = "nl-nl", 
                                            Name = "Nederland" };
    var city = new City{Country = country};
    
    var cityLocale = new CityLocale { City = city, LangCode = "nl-nl", 
                                            Name = "Amsterdam" };
    
    session.SaveOrUpdate(country);
    
    代码段1错误:

    var country = new Country();
    var countryLocale = new CountryLocale { LangCode = "nl-nl", Name = "Nederland" };
    country.CountryLocales.Add(countryLocale);
    
    var city = new City();
    var cityLocale = new CityLocale { LangCode = "nl-nl", Name = "Amsterdam" };
    city.CityLocales.Add(cityLocale);
    country.Cities.Add(city);
    
    var country = new Country();
    
    var countryLocale = new CountryLocale { Country = country,LangCode = "nl-nl", 
                                            Name = "Nederland" };
    var city = new City{Country = country};
    
    var cityLocale = new CityLocale { City = city, LangCode = "nl-nl", 
                                            Name = "Amsterdam" };
    
    session.SaveOrUpdate(country);
    
    无法将值NULL插入表的“CountryId”列中 'ArtWorld.dbo.City';列不允许空值。插入 失败。\r\n语句已终止

    片段2:

    var country = new Country();
    var countryLocale = new CountryLocale { LangCode = "nl-nl", Name = "Nederland" };
    country.CountryLocales.Add(countryLocale);
    
    var city = new City();
    var cityLocale = new CityLocale { LangCode = "nl-nl", Name = "Amsterdam" };
    city.CityLocales.Add(cityLocale);
    country.Cities.Add(city);
    
    var country = new Country();
    
    var countryLocale = new CountryLocale { Country = country,LangCode = "nl-nl", 
                                            Name = "Nederland" };
    var city = new City{Country = country};
    
    var cityLocale = new CityLocale { City = city, LangCode = "nl-nl", 
                                            Name = "Amsterdam" };
    
    session.SaveOrUpdate(country);
    
    城市和城市比例地图:

    public class CityMap : ClassMap<City>
    {
        public CityMap()
        {
            Table("City");
            Id(x => x.Id);
            References(x => x.Country).Column("CountryId").Cascade.SaveUpdate();
            HasMany(x => x.CityLocales).KeyColumn("CityId").Cascade.SaveUpdate();
        }
    }
    
    public class CityLocaleMap : ClassMap<CityLocale>
    {
        public CityLocaleMap()
        {
            Table("City_Locale");
            Id(x => x.Id);
            Map(x => x.LangCode).Not.Nullable();
            Map(x => x.Name).Not.Nullable();
            References(x => x.City).Column("CityId").Cascade.SaveUpdate();
        }
    }
    
    公共类城市地图:类地图
    {
    公共城市地图()
    {
    表(“城市”);
    Id(x=>x.Id);
    引用(x=>x.Country).Column(“CountryId”).Cascade.SaveUpdate();
    HasMany(x=>x.citycales).KeyColumn(“CityId”).Cascade.SaveUpdate();
    }
    }
    公共类城市地图:类地图
    {
    公共城市地图()
    {
    表(“城市/地区”);
    Id(x=>x.Id);
    Map(x=>x.LangCode).Not.Nullable();
    Map(x=>x.Name).Not.Nullable();
    引用(x=>x.City).Column(“CityId”).Cascade.SaveUpdate();
    }
    }
    
    这是我的国家/地区地图:

    public class CountryMap : ClassMap<Country>
    {
        public CountryMap()
        {
            Table("Country");
            Id(x => x.Id);
            HasMany(x => x.Cities).KeyColumn("CountryId").Cascade.SaveUpdate();
            HasMany(x => x.CountryLocales).KeyColumn("CountryId").Cascade.SaveUpdate();
        }
    
    }
    
    public class CountryLocaleMap :ClassMap<CountryLocale>
    {
        public CountryLocaleMap()
        {
            Table("Country_Locale");
            Id(x => x.Id);
            Map(x => x.LangCode).Not.Nullable();
            Map(x => x.Name).Not.Nullable();
            References(x => x.Country).Column("CountryId").Cascade.SaveUpdate();
        }
    }
    
    公共类CountryMap:ClassMap
    {
    公共国家地图()
    {
    表(“国家”);
    Id(x=>x.Id);
    HasMany(x=>x.Cities).KeyColumn(“CountryId”).Cascade.SaveUpdate();
    HasMany(x=>x.CountryLocales).KeyColumn(“CountryId”).Cascade.SaveUpdate();
    }
    }
    公共类CountryLocaleMap:ClassMap
    {
    公共CountryLocaleMap()
    {
    表(“国家/地区”);
    Id(x=>x.Id);
    Map(x=>x.LangCode).Not.Nullable();
    Map(x=>x.Name).Not.Nullable();
    引用(x=>x.Country).Column(“CountryId”).Cascade.SaveUpdate();
    }
    }
    
    NHibernate映射更改:

    国家/地区
    一侧

      HasMany(x => x.CountryLocales).KeyColumn("CountryId").Cascade.SaveUpdate()
    
    在乡下,你有

    References(x => x.Country).Column("CountryId").Cascade.SaveUpdate();
    
    应使用
    .inverse()
    将其中一个关系标记为反向

    .Cascase.SaveUpdate()文件
    当一个临时子实体添加到父
    Country
    CountryLocales
    列表中时,确保NHibernate管理子实体
    CountryLocale
    的生命周期。如果您不想自己显式地处理CountryLocale的生命周期,我建议将
    C中的多个标记为一个CountryLocale
    ->
    国家/地区
    反向

    有两种方法可以使您在
    CountryLocale
    中引用的
    Country
    不那么刺眼,而更加直观

    如果国家/地区管理地区

    Country
    中添加一个方法,该方法将管理正在添加的区域设置。客户端(
    Country
    CountryLocale
    的用户不需要显式地使用引用)

    CountryLocale更受域驱动

    通过重新定义它,使您不能在没有
    Country
    Country的情况下拥有
    CountryLocale

    public class CountryLocale
    {
        public CountryLocale(Country country)
        {
             this.Country = country;
        }
    
        //you need a no-agrument constructor for NHibernate
        protected CountryLocale()
        {
        }
    }
    

    NHibernate映射更改:

    国家/地区
    一侧

      HasMany(x => x.CountryLocales).KeyColumn("CountryId").Cascade.SaveUpdate()
    
    在乡下,你有

    References(x => x.Country).Column("CountryId").Cascade.SaveUpdate();
    
    应使用
    .inverse()
    将其中一个关系标记为反向

    .Cascase.SaveUpdate()文件
    当一个临时子实体添加到父
    Country
    CountryLocales
    列表中时,确保NHibernate管理子实体
    CountryLocale
    的生命周期。如果您不想自己显式地处理CountryLocale的生命周期,我建议将
    C中的多个标记为一个CountryLocale
    ->
    国家/地区
    反向

    有两种方法可以使您在
    CountryLocale
    中引用的
    Country
    不那么刺眼,而更加直观

    如果国家/地区管理地区

    Country
    中添加一个方法,该方法将管理正在添加的区域设置。客户端(
    Country
    CountryLocale
    的用户不需要显式地使用引用)

    CountryLocale更受域驱动

    通过重新定义它,使您不能在没有
    Country
    Country的情况下拥有
    CountryLocale

    public class CountryLocale
    {
        public CountryLocale(Country country)
        {
             this.Country = country;
        }
    
        //you need a no-agrument constructor for NHibernate
        protected CountryLocale()
        {
        }
    }
    

    谢谢你详尽的回答。它对我帮助很大。谢谢你详尽的回答。它对我帮助很大。