2013-04-17 11 views
18

ほとんどの場合(すべてではないにしても)、私のEntity Framework POCOに仮想関数があります。エンティティが遅延ロードされるようにこれらの関数を仮想的にする必要があります。コンストラクタで仮想関数を呼び出すのを避けるには?

コンストラクタでAccommodationsを初期化すると、コンストラクタで仮想関数が呼び出されますが、これは悪い習慣です。

しかし、コンストラクタでない場合、どうすればAccommodationsを初期化できますか?遅延ロードで

public class Venue 
{ 
    public Venue() 
    { 
     Accommodations = new HashSet<Accommodation>(); 
    } 

    public virtual ICollection<Accommodation> Accommodations { get; set; } 
} 
+1

遅延読み込みのポイントがするまで、すべてでそれを初期化する_not_です最初の使用。 –

+0

@JohnWillemse私はそれをnullにすると私は私のビューでnull例外を取得します。 –

+0

いいえ、nullをテストし、必要に応じて初期化します。その使用法のデモンストレーションについては、以下のウィレム・ダンカンの答えを参照してください。たぶん同じパターンのダニエルのコメントによれば、ここではさまざまなパターンを混乱させているかもしれません。 –

答えて

12
public class Venue 
{ 
    private accommodations_ = new HashSet<Accommodation>(); 

    public Venue() { } 

    public virtual ICollection<Accommodation> Accommodations 
    { 
     get { return accommodations_; } 
     set { accommodations_ = value; } 
    } 
} 
+3

奇妙な命名規則は何ですか?あなたは通常、アンダースコアを前方に置きます。 –

+1

@DanielHilgarth、私はそれをまったくコンベンションと呼ぶつもりはありません。私が本当に変える必要がある(おそらく悪い)習慣です; –

+0

EFは先行アンダースコアがあまり好きではありません。 – Casey

2

、あなたもそれが最初にアクセスするので、nullそれを残していますAccommodationsそれまでは初期化されません。

あなたはそれが自動に自分自身を初期化するために、次のようにラップすることができます:

private ICollection<Accommodation> _accommodations; 

public virtual ICollection<Accommodation> Accommodations { 
    get { 
     if (_accommodations == null) 
     { 
      // Initialize or load data here. 
      _accommodations = new HashSet<Accommodation>(); 
     } 
     return _accomodations; 
    } 
    set { 
     _accommodations = value; 
    } 
} 

このソリューションに関する以下のコメントを必ずお読みください!

+7

彼はORMの文脈で怠惰な読み込みについて話しています。 ORMがあなたのためにこれをすべて処理しますので、あなたの答えはその点を逃してしまいます。さらに、あなたがここに示す練習に関して[この回答](http://stackoverflow.com/questions/14774008/good-or-bad-practice-initializing-objects-in-getter/14774042#14774042)を見てください。 –

+0

良い点、毎日何かを学び、答えへのポインタを追加しました。 –

+0

ダニエルのリンクありがとう。 –

14

もう1つのオプションは、セッターをプライベートとしてマークすることです。これはコンストラクターで仮想メンバーを呼び出す問題をなくします。

これを実行したら、発信者(EF以外)がデザインで必要に応じてそのプロパティを設定する方法を提供する必要があります。オーバーロードされたコンストラクタを使用して宿泊施設のリストを渡すか、オプションでコレクション(ドメイン駆動型デザイン)をカプセル化し、アイテムを追加/削除するメソッドを使用できます(EFでは完全にカプセル化されていないためNHibernateのとは異なり、コレクション、):それはプライベート変数を使用せずに簡単にすることができ、C#6.0のデフォルトの初期設定では

public class Venue 
{ 
    public Venue() 
    { 
     Accommodations = new HashSet<Accommodation>(); 
    } 

    public Venue(ICollection<Accommodation> accommodations) 
    { 
     Accommodations = new List<Accommodation>(accommodations); 
    } 

    public virtual ICollection<Accommodation> Accommodations { get; private set; } 
} 
+2

まさに私が必要としたもの。面白いこの質問は1年以上経過していますが、私はそれを探しに行く前に、この回答をわずか4時間で投稿します! – Xcelled194

0

public class Venue 
{ 
    public virtual ICollection<Accommodation> Accommodations {get; set; } = new HashSet<Accommodation>(); 
} 
関連する問題