2

既存のデータベース (実際には IBM i 上の DB2) にアクセスしていますが、Fluent NHibernate の次の (単純な) 構造のマッピングに問題があります。私は人為的な例を作成しなければならなかったので、省略を許してください。

仕事 ...

public class Job
{
    public virtual string JobCode { get; set; }

    public virtual string Owner{ get; set; }

    public virtual IList<Deliverable> Deliverables { get; set; }

    public Job()
    {
        Deliverables = new List<Deliverable>();
    }
}

納品物..

public class Deliverable
{
    public virtual string JobCode { get; set; }

    public virtual int Package { get; set; }

    public virtual string Owner { get; set; }

    public virtual string Reference { get; set; }

    public virtual Job Job { get; set; }
}

次のように、ジョブと成果物の間の「HasMany」関係をマッピングしようとしています..

public class JobMap : ClassMap<Job>
{
    public JobMap()
    {
        Table("JOB");

        Id(x => x.JobCode).Column("CODE");

        Map(x => x.Owner).Column("WHODO");

        HasMany(x => x.Deliverables)
            .KeyColumn("CODE");
    }
}

public class DeliverableMap : ClassMap<Deliverable>
{
    public DeliverableMap()
    {
        Table("DELIVERABLE");

        Id(x => x.JobCode).Column("CODE");

        Map(x => x.Reference).Column("UNQREF");

        Map(x => x.Owner).Column("WHODO");

        References( x => x.Job) 
            .Column("CODE") ;
    }
}

これは機能しているようで、生成された SQL を直接実行すると、正しい結果が返されます (この場合は 11 レコードで、すべてが一意です)。しかし、次のことを行うと、成果物のリストには 11 個のエントリがすべて同じになります。

IList results = session .CreateCriteria(typeof(Job)) .Add(Expression.Eq("コード", "206171")) .List();

foreach (var job in results)
{
   Console.WriteLine("job.JobCode" + job.JobCode);
   Console.WriteLine("job.Owner" + job.Owner);

   foreach (var deliverable in job.Deliverables)
   {

     **// These are all identical!**

     Console.WriteLine(deliverable.Reference);
     Console.WriteLine("deliverable.Owner" + deliverable.Owner);
     Console.WriteLine(deliverable.JobNumber);
     Console.WriteLine(deliverable.DeliverableTyoe);
     Console.WriteLine(deliverable.Description);
   }
}

それで、マッピングは間違っていますか、それとも私がそれらを使用している方法に問題がありますか?

事前に感謝します。私は一日中これを見つめていました。

4

2 に答える 2

2

私はそれを修正したようです。CompositeID を成果物マッピングに追加しました

 CompositeId()
     .KeyProperty(x => x.JobCode, "CODE")
     .KeyProperty(x => x.Reference, "UNQREF");

つまり、Deliverable クラスで以下をオーバーライドする必要がありました

public override bool Equals(object obj)
{
  if (obj == null)
    return false;

  var t = obj as Deliverable;
  if (t == null)
    return false;

  if (JobCode == t.JobCode && Reference == t.Reference)
    return true;

  return false;
 }

  public override int GetHashCode()
  {
    return (JobCode + "|" + Reference).GetHashCode();
  }

そして、以下のようにジョブマッピングも変更しました

 HasMany(x => x.Deliverables)
   .KeyColumn("Codex")
   .Inverse()
   .Cascade.All();

.Inverse()これらのどれが状況を修正したかはわかりません (ジョブ マッピングにあると思われます。

生成された SQL がどのように見えるかはわかりませんが、答えは正しいようです。

于 2013-08-29T20:46:46.107 に答える
1

多対 1 の関係 (この例ではDelivarableJob) では、関係自体は1 つのDB 列で表現されます。子テーブル ( Deliverable) には、 Job ID (Code) の参照列があります (ある必要があります)

したがって、マッピングに必要なのは、ジョブとの関係を含む Delivarable テーブル内の列です。JobCode列。(上記の例から、あるかどうかはわかりません)

そして、これは両側で使用する必要があります:

配達可能:

public DeliverableMap()
{
    ...
    // References( x => x.Deliverable) ... I guess it is typo in the question snippet
    References( x => x.Job) 
        .Column("JobCode") ; // column of table Deliverable
}

仕事:

public JobMap()
{
    ...
    HasMany(x => x.Deliverables)
        .KeyColumn("JobCode");  // column of table Deliverable
}

つまり、このマッピングの両方の列名は、実際には1 つの列の名前です。どちらも子 (Deliverable) テーブルの列にマップされます。

拡張: 質問のマッピングの変更に基づく

Deliverableオブジェクトの(列 CODE) は、 ID(列 CODE) への参照と同じJobです。これは奇妙に思えます。

これは、JOB コレクション内のすべての成果物アイテムが同じ(同一) であるという事実も説明しています。一意の成果物 (コードで定義) は 1 つだけです。このシナリオのジョブは、複数の成果物を持つことはできません (一意の CODE 列によって参照されるため)。1対1のシナリオのようです。

同じものが多い理由は判断が難しいです。使用しているクエリを確認するとよいでしょう。

しかし、実際には列のマッピングを 2 回チェックします。成果物には、「JobCODE」という列にジョブへの参照が必要です...関連するより多くの成果物をサポートします...

于 2013-08-29T03:25:38.013 に答える