2012年5月14日月曜日

[NHibernate]インターフェイスのマッピング

この間ふと、「NHibernateってインターフェイスをマッピングできるのかな。」と気になったので、実験をしてみました。

どういうこと?

例えば以下のようなエンティティがあったとします。

public class Employee : IPerson
{
 public virtual int Id { get; set; }

 public virtual string Name { get; set; }

 public string FullName
 {
  get { return Name; }
 }
}
public class Customer : IPerson
{
 public virtual int Id { get; set; }

 public virtual string FirstName { get; set; }

 public virtual string LastName { get; set; }

 public string FullName
 {
  get { return LastName + " " + FirstName; }
 }
}
いずれも見ての通り IPerson というインターフェイスを実装したクラスです。

public interface IPerson
{
 string FullName { get; }
}
マッピングは以下のようにします。

<class name="Employee" table="Employees" lazy="false">
  
 <id name="Id">
  <generator class="identity"></generator>
 </id>

 <property name="Name"></property>

</class>

<class name="Customer" table="Customers" lazy="false">
  
 <id name="Id">
  <generator class="identity"></generator>
 </id>

 <property name="FirstName"></property>
 <property name="LastName"></property>

</class>
この場合に、IPerson のエンティティ全体に対してクエリを投げたりできるのか。ということです。
以下のような問い合わせを想定します。

var persons = session.Query<IPerson>();
こんなことをしたい場合、どうすればいいんだろう?という疑問です。

ちなみに、適当に以下のようなデータを入れておきます。

Employees
Id Name
1 さいとー
2 ぱず
3 ぼーま
4 いしかわ
Customers
Id FirstName LastName
1 かずんど ごうだ
2 ひでお くぜ

モノは試し

せっかくなので上記のコードを試してみます。今は IPerson なんてマッピングファイルには一切記述していないので、失敗するだろうと思って試すと...


何事も無く動いてしまいました。しかも期待通りの結果です。

NHibernateが出したログから実行されたSQLを見てみます。

select employee0_.Id as Id0_, employee0_.Name as Name0_ from Employees employee0_
select customer0_.Id as Id1_, customer0_.FirstName as FirstName1_, customer0_.LastName as LastName1_ from Customers customer0_

どうやら IPerson に対するクエリを書いたので、実装エンティティを順番に問い合わせて、結果を合わせて返してくれたようですね。たまげたなぁ。


公式サイトのドキュメントに載ってた

ここに載ってました。暗黙的ポリモーフィズムと呼ばれるタイプのマッピングアプローチのようです。

インターフェイスのマッピングに関しては、他にも数種類のアプローチがあり、また今度試して見ることにします。(ドキュメントを眺めているだけだとなんだかよくわからないので...)


気になる

ただ、この方法だと実装エンティティの数だけ問い合わせが行われてしまいますね。
また、条件や並び順を指定したときどうなるのかも少し試してみたのですが、投稿をわけてまとめたいと思います。

TFT 10.14 Peeba Comp

こちらのガイドの自分用まとめです。 https://www.reddit.com/r/CompetitiveTFT/comments/hraunp/tft_1014_break_the_meta_new_peeba_comp_set_35/ 難しいですが完成すると非常に強く、プレ...