NHibernate / FluentNHibernate属性包 [英] NHibernate/FluentNHibernate property bag

查看:116
本文介绍了NHibernate / FluentNHibernate属性包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个Vehicle类和一个VehicleProperty类...

$ $ p $ code $ public class $ $

public virtual int Id {get;保护组}
公共虚拟字符串注册{get;组; }

私人列表< VehicleProperty> _properties = new List< VehicleProperty>();
public virtual IEnumerable< VehicleProperty>属性
{
get {return _properties; }
protected set {_properties = new List< VehicleProperty>(value);}
}

public virtual void AddProperty(string name,string value)
{
_properties.Add(new VehicleProperty {Name = name,Value = value});



public class VehicleProperty
{
public virtual string Name {get;组; }
公共虚拟字符串值{get;组;如何映射这两个类,以便VehicleProperty表有一个复合[VehicleId]和[Name]的键。车辆将是一个聚合根(VehicleProperty是不访问一个Vehicle类以外)。

我已经尝试了所有我能想到的(我是NHibernate新这并不多)

  public class VehicleMap:ClassMap< Vehicle> 
{
public VehicleMap()
{
Id(x => x.Id);
Map(x => x.Registration);
HasMany(x => x.Properties)
.Inverse()
.Cascade.All();
}
}

public class VehiclePropertyMap:ClassMap< VehicleProperty>
public VehiclePropertyMap()
{
UseCompositeId()
.WithKeyProperty(x => x.Name)
.WithKeyReference(x => ; x.Vehicle,Vehicle_Id);
Map(x => x.Name);
Map(x => x.Value);






这个映射导致下面的sql和一个StaleStateException意外的行数:0;预计:1(我也不是真的想在VehicleProperty车辆财产)...

  INSERT INTOVehicle(Registration)VALUES(@ p0);选择last_insert_rowid(); @ p0 ='AA09CDE'
UPDATEVehiclePropertySET Name = @ p0,Value = @ p1 WHERE Name = @ p2 AND Vehicle_Id = @ p3; @ p0 ='Color',@ p1 ='Black',@ p2 ='Color',@ p3 =''





  • 反过来就是
    另一个的反比关系。如果
    没有其他的,那么只是不
    更新。
  • 您声明VehicleProperty.Name属性
    作为主键。如果主
    键已经初始化,NH
    认为它已经存储了,
    因此会尝试更新。 (这就是为什么你会得到这个异常。)你可以
    改变了这种行为,但是使用一个人为的主要
    键或映射波纹管是更好的

    我不知道FluentNHibernate向您展示代码。我可以告诉你它在XML中的外观。

     < class name =Vehicle> 
    < id name =Idgenerator =native/>

    < property name =注册/>

    <! - 声明属性Properties - >的Vehicle_Properties表。
    < bag name =Propertiestable =Vehicle_Propertiescascade =all-delete-orphan>

    <! - Vehicle_Properties和外键的主键 - >
    < key column =Vehicle_FK/>

    <! - 表格的内容:名称和值 - >
    < composite-element class =VehicleProperty>
    < property name =Name/>
    < property name =Value/>
    < / composite-element>
    < / bag>

    < / class>


    Given a Vehicle class and a VehicleProperty class...

    public class Vehicle
    {
        public virtual int Id { get; protected set; }
        public virtual string Registration { get; set; }
    
        private List<VehicleProperty> _properties = new List<VehicleProperty>();
        public virtual IEnumerable<VehicleProperty> Properties
        {
            get { return _properties; }
            protected set{ _properties = new List<VehicleProperty>(value);}
        }
    
        public virtual void AddProperty(string name, string value)
        {
            _properties.Add(new VehicleProperty {Name = name, Value = value});
        }
    }
    
    public class VehicleProperty
    {
        public virtual string Name { get; set; }
        public virtual string Value { get; set; }
    }
    

    How can I map the two classes so that the VehicleProperty table has a composite key of [VehicleId] and [Name]. Vehicle would be an aggregate root (VehicleProperty is not accessed outside of a Vehicle class).

    I have tried everything that I can think of (I'm new to NHibernate so that's not much)

    public class VehicleMap : ClassMap<Vehicle>
    {
        public VehicleMap()
        {
            Id(x => x.Id);
            Map(x => x.Registration);
            HasMany(x => x.Properties)
                .Inverse()
                .Cascade.All();
        }
    }
    
    public class VehiclePropertyMap : ClassMap<VehicleProperty>
    {
        public VehiclePropertyMap()
        {
            UseCompositeId()
                .WithKeyProperty(x => x.Name)
                .WithKeyReference(x => x.Vehicle, "Vehicle_Id");
            Map(x => x.Name);
            Map(x => x.Value);
        }
    }
    

    This mapping results in the below sql and a StaleStateException "Unexpected row count: 0; expected: 1" (I also don't really want to have a Vehicle property on the VehicleProperty)...

    INSERT INTO "Vehicle" (Registration) VALUES (@p0); select last_insert_rowid(); @p0 = 'AA09CDE'
    UPDATE "VehicleProperty" SET Name = @p0, Value = @p1 WHERE Name = @p2 AND Vehicle_Id = @p3; @p0 = 'Colour', @p1 = 'Black', @p2 = 'Colour', @p3 = ''
    

    解决方案

    1. Don't use composite id's.
    2. Inverse means, that this is the inverse relation of an other one. If there is no other one, it's just not updated.
    3. You declared the VehicleProperty.Name Property as the primary key. if the primary key is already initialized, NH thinks it is already stored and therefore tries an update. (that's why you get the exception.) You can changed this behaviour, but it's better to use an artificial primary key or the mapping bellow.

    I don't know FluentNHibernate to show you the code. I can tell you how it looks in XML.

    <class name="Vehicle">
      <id name="Id" generator="native"/>
    
      <property name="Registration"/>
    
      <!-- declare the table Vehicle_Properties for the property Properties -->
      <bag name="Properties" table="Vehicle_Properties" cascade="all-delete-orphan">
    
        <!-- primary key of Vehicle_Properties and foreign key -->
        <key column="Vehicle_FK"/>
    
        <!-- contents of the table: Name and Value -->
        <composite-element class="VehicleProperty">
          <property name="Name"/>
          <property name="Value"/>
        </composite-element>
      </bag>
    
    </class>
    

    这篇关于NHibernate / FluentNHibernate属性包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆