0

マッピングしているデータベースには Plan エンティティが含まれています。各 Plan エンティティには、主要な部門 (多対 1 の関係) と、可能な追加部門のバッグ (多対多の関係) があります。部門は、'ID' 列と 'NAME' 列のみを持つルックアップ テーブルに格納されます。「PLAN」テーブルには「DEPARTMENT_ID」外部キー列があり、メインの部門を参照するために「DEPARTMENT」テーブルの ID を格納します。計画と追加の部門との関係は、「PLAN_ID」および「DEPARTMENT_ID」列を持つ相互参照表に保管されます。

これで、Plan クラスと Department クラスを使用して、この構造を正常にマッピングできました。

public class Plan
{
    public virtual int Id { get; set; }

    public virtual Department ExecutorDepartment { get; set; }

    public virtual IList<Department> AdditionalExecutorDepartments { get; set; }
}

public class Department
{
    public virtual int Id { get; set; }

    public virtual string Name { get; set; }
}

<class name="Plan" table="PLAN">
  <id name="Id" unsaved-value="0">
    <column name="ID" not-null="true" />
    <generator class="native"/>
  </id>
  <many-to-one name="ExecutorDepartment" class="Department" column="DEPARTMENT_ID"/>
  <bag name="AdditionalExecutorDepartments" table="PLAN_DEPARTMENT">
    <key column="PLAN_ID" />
    <many-to-many class="Department" column="DEPARTMENT_ID"></many-to-many>
  </bag>
</class>
<class name="Department" table="DEPARTMENT">
  <id name="Id" unsaved-value="0">
    <column name="ID" not-null="true" />
    <generator class="native"/>
  </id>
  <property name="Name" column="NAME" type="string"/>
</class>

ただし、Department クラス (アプリケーション ロジックに関する限り、これはまったく役に立たない) を削除し、次のように Plan クラスに部門名を文字列として格納する方法を探しています。

public class Plan
{
    public virtual int Id { get; set; }

    public virtual string ExecutorDepartment { get; set; }

    public virtual IList<string> AdditionalExecutorDepartments { get; set; }
}

それを行う方法はありますか?言っておきますが、データベースのデータを更新するつもりはありません。また、データベースの構造を変更することもできません。

PS<Join>要素を使用して主要な部門を取得しようとしましたが、どうやら主キーでしか参加できないようです(https://nhibernate.jira.com/browse/NH-1452を参照)。

4

1 に答える 1

1

ほとんどの場合、Department クラスはまったく役に立たないわけではありません。次のコードはどういう意味ですか?

plan.ExecutorDepartment = "Hyoomun Reesorsis";
plan.ExecutorDepartment = "Human Resources";

スペルを修正しているだけなのか、それとも別の部門に割り当てているのかわかりません.

部署の名前が変わる可能性はありますか? その場合、その変更はその部門に属するすべての計画に反映する必要がありますか? その場合、ドメイン駆動設計の観点からすると、部門は値オブジェクトではなくエンティティです。エンティティの場合は、これらの関係をmany-to-oneおよびで引き続きマッピングする必要がありmany-to-manyます。これにより、コードがよりわかりやすくなります。スペルを修正するには、次のように言います...

plan.ExecutorDepartment.Name = "Human Resources";

... または、計画を新しい部門に割り当てるには、次のように言います。

plan.ExecutorDepartment = theOtherHrDepartmentThatActuallyCaresAboutSpelling;

このバージョンのコードは、何をしようとしているのかがより明確になっています。

NHibernate は、オブジェクト指向のドメイン駆動型の方法でリレーショナル データベースを操作できるようにするツールです。DDD ルールに従おうとする場合に最適です。あなたが求めていることは、DDD の観点からは意味がありませ。Department には ID があるため、NHibernate は ID を持たないふりをサポートしていません。やりたいことのマッピングはありません。このようにモデル化する必要がある場合、いくつかのオプションがあります。

A. プロパティを追加して掘り下げ、文字列を取得します。

public virtual string ExecutorDepartmentName
{
    get { return ExecutorDepartment != null ? ExecutorDepartment.Name : null; }
}

public virtual IEnumerable<string> AdditionalExecutorDepartmentNames
{
    get { return AdditionalExecutorDepartments.Select(x => x.Name); }
}

B. データベース スキーマを変更し、テーブルを削除して、すべての列をDepartmentに置き換えます。部署が実際にはエンティティではなく値オブジェクトであると想定されている場合は、これを行ってください。スキーマを変更した後、マッピングを and から and に変更する必要があります。Department_idDepartmentNamemany-to-onebag many-to-manypropertybag element

C. オプション "A" に似ているが、変更せずに部門を変更できるようにしたい場合Department_id-Departmentの主キーを文字列名に変更すると、そのようなものを取得できます (ただし、一意であり、null ではありません)。これによりsession.Load、データベースにアクセスすることなく、文字列名から Department インスタンスを取得できます。

したがって、これはおそらく、あなたが望んでいた「あなたが知らなかったこの素晴らしいマッピングです」という特効薬ではありませんが、これらはすべて私が考えることができる現実的なオプションであり、あなたは見つけることができるはずです.このリスト内のニーズを満たすもの。

于 2013-11-01T20:53:55.917 に答える