【问题标题】:NHibernate, adding children via parent vs setting reference to parent on childrenNHibernate,通过父级添加子级与在子级上设置对父级的引用
【发布时间】:2013-03-29 12:11:08
【问题描述】:

我目前正在处理我的第一个 NHibernate 项目。

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

  1. 当我在子节点上设置对父节点的引用时,它正在工作(尽管这对我来说并不自然,请参见代码 sn-p
  2. 这是正常行为还是我做错了什么?

片段 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);

片段 1 错误:

无法将值 NULL 插入“CountryId”列,表 'ArtWorld.dbo.City';列不允许空值。插入 失败。\r\n语句已终止。

sn-p 2:

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);

城市和 CityLocale 地图:

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();
    }
}

这是我的国家/地区地图:

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();
    }
}

【问题讨论】:

    标签: nhibernate fluent-nhibernate nhibernate-mapping


    【解决方案1】:

    NHibernate 映射更改:

    Country 方面你有

      HasMany(x => x.CountryLocales).KeyColumn("CountryId").Cascade.SaveUpdate()
    

    在 CountryLocale 方面你有

    References(x => x.Country).Column("CountryId").Cascade.SaveUpdate();
    

    其中一个关系应使用.Inverse() 标记为逆关系。

    .Cascase.SaveUpdate() 确保 NHibernate 在将临时子实体添加到父 CountryCountryLocales 列表时管理子实体 CountryLocale 的生命周期。如果您不想自己明确处理 CountryLocale 的生命周期,我建议将 CountryLocale -> Country 的多对一一侧标记为 Inverse

    有两种方法可以让您在 CountryLocale 中引用 Country酸眼更多直观 p>

    如果国家/地区管理区域设置

    Country 中添加一个方法,该方法将管理正在添加的语言环境。客户端(CountryCountryLocale 的用户无需明确使用引用)

    public virtual bool AddCountryLocales(CountryLocale locale)
    {
            if(!this.CountryLocales.Contains(locale))
            {
                  locale.Country =this;
                  this.CountryLocales.Add(locale);
                  return true;  
            }
            return false;
    }
    

    CountryLocale 更受域驱动

    通过重新定义它,使CountryLocale 不能没有Country

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

    【讨论】:

    • 感谢您的广泛回答。这对我帮助很大。
    猜你喜欢
    • 2015-05-22
    • 1970-01-01
    • 2017-02-18
    • 2020-03-21
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    相关资源
    最近更新 更多