2010-12-07 2 views
1

Ich habe ein Unternehmen, das wie folgt aussieht:Wie mache ich einen OfType <>(). Count() auf eine heterogene Sammlung in NHibernate?

public class Album 
{ 
    public virtual string Name { get; set; } 
    public virtual IEnumerable<Media> { get; set; } 

    public virtual IEnumerable<Picture> 
    { 
     get { return Media.OfType<Picture>(); } 
    } 

    public virtual IEnumerable<Video> 
    { 
     get { return Media.OfType<Video>(); } 
    } 

    public virtual IEnumerable<Audio> 
    { 
     get { return Media.OfType<Audio>(); } 
    } 
} 

Wo Media die abstrakte Basisklasse ist und Picture, Video und Audio sind Subtypen von Media, so dass die IEnumerable<Media> Sammlung heterogener ist.

Ich habe einen DTO für Album die wie folgt aussieht:

public class AlbumDTO 
{ 
    public string Name { get; set; } 
    public int PictureCount { get; set; } 
    public int VideoCount { get; set; } 
    public int AudioCount { get; set; } 
} 

Wo jede Zählung indem <collection>.Count(); bevölkert wird. Obwohl dieser Code funktioniert gut und ich die Zählung für jeden Medientyp zu erhalten, ist die erzeugte SQL weniger als ideal:

SELECT * FROM Media WHERE media.Album_id = 1 
SELECT * FROM Media WHERE media.Album_id = 2 
SELECT * FROM Media where media.Album_id = 3 

Mit anderen Worten, alle es greift die Media zuerst aus der Datenbank und dann die OfType<T>.Count() danach Durchführung in Erinnerung. Das Problem ist, wenn ich dies über alle Albums mache, wird es alle Media aus der Datenbank auswählen, die möglicherweise Tausende von Datensätzen sein könnte. Ich würde Vorzugsweise mag so etwas sehen (ich verwende Tabelle pro Hierarchie Mapping):

SELECT COUNT(*) FROM Media WHERE media.Album_id = 1 AND discriminator = 'Picture' 
SELECT COUNT(*) FROM Media WHERE media.Album_id = 1 AND discriminator = 'Video' 
SELECT COUNT(*) FROM Media WHERE media.Album_id = 1 AND discriminator = 'Note' 

Wer weiß, wie ich NHibernate dies tun konfigurieren können? Oder muss ich meine Album Entität ändern, um das richtige Verhalten zu erhalten?

+0

veröffentlichen Sie Ihre Konfig. Verwenden Sie Fluent Nhibernate? – Aliostad

+0

Ich verwende Fluent NHibernate mit automapping. Es verwendet nur die Standardkonventionen. –

Antwort

2

Zunächst wird Ihr Code nicht kompilieren; Sie vermissen den Namen der Eigenschaft der IEnumerable<Media> (ich nehme an, es ist Media) und auch der Filter.

Zweitens müssen Sie ein wenig darüber verstehen, was vor sich geht. Aufgrund dieses Verhaltens bin ich mir ziemlich sicher, dass Sie Ihr Album mit einer HasMany-Beziehung zu Media verknüpft haben. Wenn Sie das Album zum ersten Mal aus der Datenbank abrufen, erhält Media einen Verweis auf ein NHibernate-Objekt namens PersistentBag. Dies ist einfach ein Platzhalter, der wie ein IEnumerable aussieht und die Logik enthält, um die echte Liste zu füllen, wenn sie tatsächlich benötigt wird. Alles, was es tun kann, ist, die Datensätze, wie sie im HBM abgebildet sind, zu ziehen, wenn die Methode GetEnumerator() aufgerufen wird (und das passiert praktisch in jeder Linq-Methode). Wenn Sie also OfType aufrufen, arbeiten Sie nicht mehr mit einem NHibernate IQueryable, das eine SQL-Anweisung erstellen kann, die genau das tut, was Sie wollen. Stattdessen werden Sie nach jedem Element in der Liste gefragt, von dem Sie glauben, dass es bereits vorhanden ist, und NHibernate entspricht.

Sie haben einige Optionen, wenn alles, was Sie wollen, die Anzahl ist. Am einfachsten, wenn möglich, ist einfach auf die Session zurück zu gehen und für eine ganz neue Abfrage auf Album fragen:

session.Linq<Album>().Where(a=>a.Id = 1).Select(a=>a.Media.OfType<Picture>()).Count(); 

Dies wird direkt eine Erklärung erstellen, die an die DB geht und bekommen die Anzahl der Datensätze. Sie laden nichts, Sie fragen das Repository nach einer Zählung, die es direkt in SQL übersetzt.

Verwandte Themen