문제

차량 클래스와 차량 분야 클래스가 주어져 ...

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

VehicleProperty 테이블에 [Vehicle] 및 [name]의 복합 키가 있도록 두 클래스를 어떻게 매핑 할 수 있습니까? 차량은 집계 루트가 될 것입니다 (차량 장애는 차량 클래스 외부에서는 액세스되지 않음).

나는 내가 생각할 수있는 모든 것을 시도했다.

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"을 초래합니다.

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. 복합 ID를 사용하지 마십시오.
  2. 역 반대는 이것이 다른 것의 역 관계라는 것을 의미합니다. 다른 것이 없다면 업데이트되지 않습니다.
  3. VehicleProperty.name 속성을 기본 키로 선언했습니다. 기본 키가 이미 초기화되면 NH는 이미 저장되어 업데이트를 시도한다고 생각합니다. (그렇기 때문에 예외를 얻는 이유입니다.)이 동작을 변경할 수는 있지만 인공 기본 키나 매핑 벨로우를 사용하는 것이 좋습니다.

나는 당신에게 코드를 보여주기 위해 fluentnhibernate를 모른다. 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로 문자 그대로 번역 된 것은 다음과 같습니다.

public class VehicleMap : ClassMap<Vehicle>
{
  public VehicleMap()
  {
    Id(x => x.Id);
    Map(x => x.Registration);

    HasMany(x => x.Properties)
      .Component(c =>
      {
        c.Map(x => x.Name);
        c.Map(x => x.Value);
      })
      .Cascade.AllDeleteOrphan();
  }
}

먼저 복합 PK에 대한 별도의 클래스를 만듭니다.

public class VehiclePropertyPK
{
  public virtual Vehicle PropertyVehicle { set; get; }
  public virtual string Name { set; get; }

  // You must implement your own GetHasCode and Equals methods
  public override int GetHashCode()
  {
    ...
  }

  public override bool Equals(object o)
  {
    ...
  }
}

그런 다음 refactor VehicleProperty 이런 식으로 수업 :

public class VehicleProperty
{
  public virtual VehiclePropertyPK VehicleCompId { get; set; }
  public virtual string Value { get; set; }
}

마지막으로지도 :

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

public class VehiclePropertyMap : ClassMap<VehicleProperty>
{
  public VehiclePropertyMap()
  {
    CompositeId<VehiclePropertyPK>(x => x.VehicleCompId)
            .KeyReference(y => y.PropertyVehicle , "Vehicle_Id")
            .KeyProperty(y => y.Name, "Name");
    Map(x => x.Value);
  }
}

(nhibernate 3.3.1 및 fluentnhibernate 1.3.0)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top