2012-06-21 27 views
23

Ich möchte wissen, was ist der Unterschied zwischen dem Erstellen von Klassen mit oder ohne Verwendung von "hashset" im Konstruktor.mit Hashset in Entity Framework

Code ersten Ansatz (4.3) kann man Modelle wie diese Creat:

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; } 
} 

oder Modelle wie folgt erstellen:

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; } 

} 

Was hier tut Hashset?

sollte ich in den ersten beiden Modellen auch hashset verwenden?

Gibt es einen Artikel, der die Anwendung von hashset zeigt?

Antwort

12

Ich bin ziemlich neu in Entity Framework, aber das ist mein Verständnis. Die Auflistungstypen können alle Typen sein, die implementieren. Meiner Meinung nach ist ein HashSet normalerweise der semantisch korrekte Sammlungstyp. Die meisten Sammlungen sollten nur eine Instanz eines Mitglieds haben (keine Duplikate) und HashSet drückt dies am besten aus. Ich habe meine Kurse wie unten gezeigt geschrieben und das hat bisher gut funktioniert. Beachten Sie, dass die Sammlung als ISet<T> eingegeben wird und der Setter privat ist.

+1

stimme ich voll und ganz zu. In den meisten Fällen ist das 'HashSet' * die natürlichste Form. –

+0

hashset scheint immer noch richtig in EF6.x. Nativ verwendet EF bei der db-first-Erstellung von Typen genau so Hash-Sets. –

16

Im Allgemeinen ist es am besten, die Sammlung zu verwenden, die am besten Ihre Absichten ausdrückt. Wenn Sie nicht beabsichtigen, die einzigartigen Eigenschaften des HashSets zu verwenden, würde ich es nicht verwenden.

Es ist ungeordnet und unterstützt keine Suche nach Index. Darüber hinaus ist es nicht so gut für sequenzielle Lesevorgänge geeignet wie andere Sammlungen, und die Tatsache, dass Sie dasselbe Element mehrfach hinzufügen können, ohne Duplikate zu erstellen, ist nur dann nützlich, wenn Sie einen Grund haben, es zu verwenden. Wenn das nicht Ihre Absicht ist, kann es Code verbergen und Probleme schwierig zu isolieren machen.

Das HashSet ist vor allem in Situationen nützlich, in denen die Einsetz- und Entfernungszeiten sehr wichtig sind, z. B. bei der Verarbeitung von Daten. Es ist auch äußerst nützlich für den Vergleich von Datensätzen (wiederum bei der Verarbeitung) mit Operationen wie "Schnittmenge", "außer" und "Vereinigung". In jeder anderen Situation überwiegen die Nachteile im Allgemeinen die Profis.

Beachten Sie, dass beim Arbeiten mit Blogposts Einfügungen und Löschungen im Vergleich zu Lesevorgängen recht selten sind und Sie die Daten in der Regel in einer bestimmten Reihenfolge lesen möchten. Das ist mehr oder weniger das genaue Gegenteil von dem, was der HashSet gut macht. Es ist höchst zweifelhaft, dass Sie jemals beabsichtigen, den gleichen Post aus irgendeinem Grund zweimal hinzuzufügen, und ich sehe keinen Grund, warum Sie Set-basierte Operationen für Posts in einer solchen Klasse verwenden würden.

8

Der HashSet definiert nicht den Typ der Sammlung, die generiert wird, wenn Sie tatsächlich Daten abrufen. Dies wird immer vom Typ ICollection wie deklariert sein.

Das HashSet, das im Konstruktor erstellt wird, soll Ihnen helfen, NullReferenceExceptions zu vermeiden, wenn keine Datensätze abgerufen werden oder auf vielen Seiten der Beziehung vorhanden sind. Es ist in keiner Weise erforderlich.

zum Beispiel basierend auf Ihre Frage, wenn Sie versuchen, eine Beziehung zu verwenden, wie ...

var myCollection = Blog.Posts(); 

Wenn keine Beiträge vorhanden sind, dann wird myCollectionnull sein.Welches ist OK, bis Sie fließend Kette Dinge und wie

etwas tun
var myCollectionCount = Blog.Posts.Count(); 

, die mit einem NullReferenceException Fehler.

Wo, wie

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

in und leer ICollection und eine Nullzählung führen. Keine Ausnahmen :-)

+2

Sind die '()' auf Eigenschaften gültig ('Blog.Posts()')? Sollte es nicht nur 'Blog.Posts' sein, auf das Feld zuzugreifen? – bradlis7

+0

Das scheint falsch zu sein. Der Debugger zeigt mir genau den Typ, den ich in meinem Konstruktor verwende, selbst für Daten, die aus der Datenbank geholt werden. Dies spiegelt sich auch in verschiedenen Verhaltensweisen beim Zugriff auf die Sammlung wider (z. B. durch DataBinding für diese Sammlungen). – linac

+1

@linac Es ist nicht das HashSet, das den Rückgabetyp definiert, sondern die Definition der ICollection-Eigenschaft . Mit dem HashSet wird nur die ICollection-Eigenschaft initialisiert. Wenn Sie die Eigenschaft im Konstruktor nicht initialisieren, zeigt der Debugger weiterhin den ICollection-Typ wie definiert an. Nichts mit dem HashSet zu tun !! – NER1808