2012-06-21 5 views
23

コンストラクタで "ハッシュセット"を使用する場合と使用しない場合のクラスの作成の違いを知りたいと思います。エンティティフレームワークでハッシュセットを使用する

public class Blog 
{ 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public string BloggerName { get; set;} 
    public virtual ICollection<Post> Posts { get; set; } 
    } 

public class Post 
{ 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public DateTime DateCreated { get; set; } 
    public string Content { get; set; } 
    public int BlogId { get; set; } 
    public ICollection<Comment> Comments { get; set; } 
} 

または、このようなモデルを作成することができます:

1は、このようなモデルをレコード生成することができ、コードの最初のアプローチ(4.3)を使用して

public class Customer 
{ 
    public Customer() 
    { 
     BrokerageAccounts = new HashSet<BrokerageAccount>(); 
    } 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public ICollection<BrokerageAccount> BrokerageAccounts { get; set; } 
} 

public class BrokerageAccount 
{ 

    public int Id { get; set; } 
    public string AccountNumber { get; set; } 
    public int CustomerId { get; set; } 

} 

HashSetのは、ここで何をしているのですか?

私は最初の2つのモデルでもハッシュセットを使用する必要がありますか?

ハッシュセットの適用を示す記事はありますか?

答えて

12

私はEntity Frameworkをかなり新しくしていますが、これは私の理解です。コレクション型は、ICollection<T>を実装する任意の型にすることができます。私の意見では、通常、HashSetは意味的に正しいコレクション型です。ほとんどのコレクションはメンバのインスタンスを1つしか持たず(重複はありません)、HashSetはこれを最もよく表しています。私は下に示すように自分のクラスを書いていますが、これまでこれまでうまくいきました。コレクションはISet<T>と入力され、セッターはプライベートであることに注意してください。

public class Customer 
{ 
    public Customer() 
    { 
     BrokerageAccounts = new HashSet<BrokerageAccount>(); 
    } 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public ISet<BrokerageAccount> BrokerageAccounts { get; private set; } 
} 
+1

私は完全に同意します。ほとんどの場合、 'HashSet' *は最も自然なフィットです。 –

+0

ハッシュセットはまだEF6.xでは正しいようです。ネイティブに、EFは型のdb-first作成時にもこの正確な方法でハッシュセットを使用します。 –

16

一般的には、あなたの意図を最もよく表すコレクションを使用することをお勧めします。特にHashSetのユニークな特性を使用するつもりがない場合、私はそれを使用しません。

索引による索引付けは順不同であり、サポートされていません。さらに、他のコレクションと同様にシーケンシャル読み取りには適していないし、同じアイテムを重複して何度も追加できるという事実は、それを使う理由があれば便利です。それがあなたの意図でない場合、誤ったコードを隠し、問題を分離しにくくすることができます。

HashSetは、データの処理時など、挿入と削除の時間が非常に重要な場合に最も役立ちます。また、intersect、except、およびunionなどの演算を使用してデータのセットを比較する場合にも非常に便利です。他のいかなる状況においても、一般的に、賛否両論は長所を上回る。

ブログの投稿を扱う場合、挿入と削除は読み込みに比べて非常に稀で、通常は特定の順序でデータを読みたいと考えています。これは、HashSetがうまくいくものとは正反対です。何らかの理由で同じ投稿を2度追加しようとすることは疑う余地がありません。そのようなクラスの投稿にセットベースの操作を使用する理由はありません。

8

HashSetは、実際にデータをフェッチするときに生成されるコレクションの種類を定義しません。これは、宣言された型のICollectionになります。

コンストラクタで作成されるHashSetは、レコードがフェッチされていない場合や、関係の多くの側に存在しない場合にNullReferenceExceptionsを回避するのに役立ちます。それは決して必要ではありません。何の記事が存在しない場合は、のような関係を利用しようとすると、あなたの質問に基づいて、例えば

、...

var myCollection = Blog.Posts(); 

そしてmyCollectionnullになります。これはあなたの流暢チェーンの事まで、OKであるとNullReferenceExceptionとエラーになります

var myCollectionCount = Blog.Posts.Count(); 

ような何かを行います。

var myCollection = Customer.BrokerageAccounts(); 
var myCollectionCount = Customer.BrokerageAccounts.Count(); 

ように、空いるICollectionなります

とゼロカウント。例外なし:-)

+2

'()'のプロパティは有効ですか( 'Blog.Posts()')?フィールドにアクセスするのに 'Blog.Posts'だけではいけませんか? – bradlis7

+0

これは間違っているようです。デバッガは、データベースからフェッチされたデータの場合でも、私のコンストラクタで使用する型を正確に示しています。これは、コレクションにアクセスするとき(たとえば、それらのコレクションのDataBindingを介して)異なる動作にも反映されます。 – linac

+1

@linac戻り値の型を定義するのはHashSetではなく、ICollection プロパティの定義です。 HashSetは、ICollectionプロパティを初期化するためにのみ使用されます。コンストラクターでプロパティーを初期化しないと、デバッガーは定義されたICollectionタイプを表示します。ハッシュセットとは関係ありません! – NER1808

関連する問題