私は新しいプロジェクトに取り掛かるたびに自分自身と精神的な議論を持ち、POCOを設計しています。 外部キーの関連付けを好むと思われる多くのチュートリアル/コードサンプルを見てきました。
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; } // <-- Customer ID
...
}
独立した関連付けとは対照的に:
public class Order
{
public int ID { get; set; }
public Customer Customer { get; set; } // <-- Customer object
...
}
私は過去にNHibernateを使用し、独立した関連付けを使用しました。これは、オブジェクト指向をより多く感じるだけでなく、(遅延読み込みを使用すると)IDだけでなくCustomerオブジェクト全体にアクセスできるという利点があります。これにより、たとえばOrderインスタンスを取得してからOrder.Customer.FirstName
結合を明示的に行う必要がなく、非常に便利です。
要約すると、私の質問は次のとおりです。
ORMを最大限に活用したい場合は、必ずエンティティ参照を使用してください。
public class Order
{
public int ID { get; set; }
public Customer Customer { get; set; } // <-- Customer object
...
}
FKを使用してデータベースからエンティティモデルを生成すると、常にエンティティ参照が生成されます。それらを使用したくない場合は、EDMXファイルを手動で変更し、FKを表すプロパティを追加する必要があります。少なくともこれは、独立した関連付けのみが許可されているEntity Framework v1の場合です。
Entity Framework v4は、外部キーの関連付けと呼ばれる新しいタイプの関連付けを提供します。独立キーと外部キーの関連付けの最も明らかな違いは、Orderクラスです。
public class Order
{
public int ID { get; set; }
public int CustomerId { get; set; } // <-- Customer ID
public Customer Customer { get; set; } // <-- Customer object
...
}
ご覧のとおり、FKプロパティとエンティティ参照の両方があります。 2種類の関連付けにはさらに違いがあります。
独立した協会
ObjectStateManager
の個別のオブジェクトとして表されます。独自のEntityState
があります!外部キーの関連付け
ObjectStateManager
の個別のオブジェクトとして表されません。そのため、いくつかの特別なルールに従う必要があります。外部キーの関連付けを使用する場合は、エンティティデータモデルウィザードでモデルに外部キー列を含めるを選択する必要があります。
編集:
これら2つのタイプの関連付けの違いはあまり知られていないことがわかったので、 短い記事を書いた これについてさらに詳しく説明し、これについての私自身の意見を述べました。
両方を使う。そして、エンティティ参照を仮想化し、遅延読み込みを可能にします。このような:
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; } // <-- Customer object
...
}
これにより、不必要なDBルックアップが節約され、遅延読み込みが可能になり、必要なIDがわかっている場合はIDを簡単に確認/設定できます。両方を持っていても、テーブル構造はまったく変更されないことに注意してください。
独立した関連付けは AddOrUpdate
ではうまく機能しません。これは通常 Seed
メソッド。参照が既存のアイテムである場合、再挿入されます。
// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);
// New order.
var order = new Order { Id = 1, Customer = customer };
db.Set<Order>().AddOrUpdate(order);
その結果、既存の顧客が再挿入され、新しい(再挿入された)顧客が新しい注文に関連付けられます。
外部キーの関連付けを使用してIDを割り当てる場合を除きます。
// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);
// New order.
var order = new Order { Id = 1, CustomerId = customer.Id };
db.Set<Order>().AddOrUpdate(order);
予想される動作があり、既存の顧客は新しい注文に関連付けられます。
不要なルックアップを避けるために、オブジェクトアプローチを好みます。ファクトリーメソッドを呼び出してエンティティ全体を構築する場合(ネストされたエンティティの単純なコールバックコードを使用)、プロパティオブジェクトを簡単に設定できます。メモリ使用量を除いて、私が目にする不利な点はありません(しかし、オブジェクトを正しくキャッシュしますか?)。そのため、あなたがしているのは、スタックをヒープに置き換え、ルックアップを実行しないことでパフォーマンスを向上させることだけです。これが理にかなっていることを願っています。