【问题标题】:Nhibernate one-to-many element addingNhibernate 一对多元素添加
【发布时间】:2015-01-05 08:28:35
【问题描述】:

我阅读了很多关于此的讨论,但找不到解决方案。 There 我发现在 nhibernate 版本 3 中必须有效。我使用休眠 3.3.3

设备有很多 Ips

public class Device
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual string Place { get; set; }

    private Iesi.Collections.Generic.ISet<Ip> _ips = new HashedSet<Ip>();

    public virtual Iesi.Collections.Generic.ISet<Ip> Ips
    {
        get
        {
            return _ips;
        }
        set
        {
            _ips = value;
        }
    }
}          

public class Ip
{
    public virtual int Id { get; set; }
    public virtual Device Device { get; set; }
    public virtual string Adress { get; set; }
}

映射

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="nhibbd" namespace="nhibbd.Domain">
  <class name="Device" table="devices" lazy="true">
    <id name="Id">
      <generator class="identity" />
    </id>
    <property name="Name">
      <column name="name" sql-type="character varying" not-null="true"  length="30"/>  
    </property>
    <property name="Place" >
      <column name="place" sql-type="character varying" not-null="true"  length="30"/>
    </property>
    <set name="Ips" inverse="false" cascade="all" generic="true">
      <key column="device_id" not-null="true" update="false"/>
      <one-to-many class="nhibbd.Domain.Ip" />
    </set>
  </class>  
</hibernate-mapping>

<hibernate-mapping assembly="nhibbd" namespace="nhibbd.Domain" xmlns="urn:nhibernate-mapping-2.2">
  <class name="Ip" table="ips" lazy="true" >
    <id name="Id">
  <generator class="identity" />
</id>
    <many-to-one name="Device" class="Device">
      <column name="device_id" not-null="true" sql-type="INTEGER" />
    </many-to-one>
    <property name="Adress">
      <column name="adress" sql-type="character varying" not-null="true" length="12"/>
    </property>
  </class>
</hibernate-mapping>

只是想添加设备

var device = new Device {Name = "D-Link DIR 320", Place = "320 room"};
var ip = new Ip {Adress = "1921680000001"};
using (var session = GetSession)
using (var transaction = session.BeginTransaction())
{
    device.Ips.Add(ip);
    session.Save(device);
    transaction.Commit();
}

得到异常

NHibernate.PropertyValueException:非空属性引用了空值 或瞬态值 nhibbd.Domain.Ip.Device

我想将 inverse="false" 用于收集,not-null="true" 用于 Ip.Device 值。我怎样才能做到这一点?

【问题讨论】:

    标签: c# nhibernate orm mapping one-to-many


    【解决方案1】:

    要解决您的问题,我们首先必须正确设置域模型。这意味着,关系的两边都必须赋值:

    using (var transaction = session.BeginTransaction())
    {
        device.Ips.Add(ip);
        // new line
        ip.Device == device;
        session.Save(device);
        transaction.Commit();
    }
    

    稍后,当我们通过 NHibernate 加载数据时,我们希望两端都正确启动。我们在创建实例时也应该这样做。

    我。 inverse="false"

    现在,如果您可以将“ips”表中的“device_id”列设为可空......那将有效。但是因为你已经明确声明了 inverse="false" (默认设置),NHibernate 必须并且总是会

    1. 将记录插入到 ips 表中,NULL 表示与父 (device_id) 列的关系
    2. 将引用 id 的记录更新到其父项(device_id 将更新为正确的设备引用)

    这将永远发生。如果 inverse="false"

    二。 inverse="true"

    因为我们已经提到,无论如何都必须在 C# 中定义关系的两端——根本没有必要不使用 NHibernate 的强大功能......

    只需使用到 inverse="true" 的映射并:

    • 将发出 INSERT 以添加新的 Ip 记录,其与设备的正确关系(device_id 列)

    这种映射实际上是为我们准备的。为了优化数据处理,基于我们在代码中正确设置关系的信任。

    一般来说,我几乎不记得不使用逆双向映射的情况......

    【讨论】:

    • 是否有办法将not-null ="true" 保留为Ip.Device 值,而不是在代码中手动设置ip.Device == device;
    • 我想说:这是一个错误在我们的代码中不使用ip.Device == device; 这是域模型设置。无论 ORM 和持久性如何,这都是关系的工作方式。如果是 our-in-memory-cache-for-play ...没有人会做那个设置。我们必须这样做。必须...希望它有所帮助 ;) 享受惊人的 NHibernate ;)
    猜你喜欢
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    相关资源
    最近更新 更多