Domanda

Sto usando NH Criteri per recuperare un'entità e progetto selettiva campi su una classe personalizzata (un po ' come proiezione di dati su un ViewModel per la visualizzazione su MVC vista).

Questo è abbastanza facile utilizzando ProjectionList:

var emailCriteria = mSession.CreateCriteria<Email>();
emailCriteria.SetProjection(
    Projections.ProjectionList()
        .Add(Projections.Property("Subject"), "Subject")
);
emailCriteria.SetResultTransformer(Transformers.AliasToBean<EmailDataModel>());
var result = emailCriteria.List<EmailDataModel>();

Tuttavia, la mia entità contiene una raccolta, e voglio portare che troppo indietro, e il progetto come una raccolta sulla mia classe personalizzata.

Il mio modello di dominio sembra (in forma semplificata) come questo:

public class Email {
    public string Subject
    public List<EmailAttachment> Attachments
    etc...
}

public class EmailAttachment {
    public UploadedFile File
}

public class UploadedFile {
    public string Filename
    public UploadedFileData Data
}

public class UploadedFileData {
    public byte[] Data
}

Ecco il "modello dei dati" classi voglio progetto su:

public class EmailDataModel {
    public string Subject
    public List<EmailAttachmentDataModel> Attachments
}

public class EmailAttachmentDataModel {
    public string Filename
    public byte[] Data
}

Ora so che questi modelli sono molto simili, e devi essere perdonato per pensare "che cosa è il punto?", ma perché ho semplificato il loro.E ' bello essere in grado di appiattire il mio dominio oggetti in pratici e modelli di dati.

Il mio grosso problema è capire come accedere i campi necessari dal profondo del mio bambino di oggetti (in questo caso, UploadedFile.Filename e UploadedFileData.Dati) e il progetto come un EmailAttachmentDataModel collezione sul mio EmailDataModel.

Ho letto un sacco di articoli che trattano l'accesso a collezioni bambino - utilizzando EmailCriteria.CreateAlias o EmailCriteria.CreateQuery - ma non ho trovato nulla che spiega come il progetto di un bambino che raccoglie la collezione.

Spero che questo sia un esercizio utile per chiunque sia interessato ad armeggiare con NH Criteri di query.

È stato utile?

Soluzione

Ok, penso di aver risolto questo aggiornamento per NHibernate 3 e utilizzando QueryOver.Ecco il mio codice simile a ora:

//Declare entities
Email email = null;
EmailAttachment attachment = null;
UploadedFile file = null;
Byte[] fileData = null;

//Select data from parent and child objects
var results = mSession.QueryOver<QueuedEmail>(() => email)
   .JoinAlias(() => email.Attachments, () => attachment, JoinType.LeftOuterJoin)
   .JoinAlias(() => attachment.File, () => file, JoinType.LeftOuterJoin)
   .JoinAlias(() => file.Data, () => fileData, JoinType.LeftOuterJoin)
   .TransformUsing(Transformers.DistinctRootEntity)
   .List<Email>()

   //Loop through results projecting fields onto POCO
   .Select(x => new EmailDataModel()
   {
       Id = x.Id,
       Body = x.Body,
       AttachmentCount = x.Attachments.Count(),
       FromAddress = x.FromAddress,
       //Loop through child collection projecting fields onto POCO
       Attachments = x.Attachments.Select(attach => new EmailAttachmentDataModel()
       {
           Data = attach.File.Data.Data,
           Filename = attach.File.Filename,
           Id = attach.Id
       }).ToArray() //NB Now projecting this collection as an array, not a list
   }).ToArray();

Quindi non c'è.Il nostro risultato è appiattita classe che contiene i dati di cui abbiamo bisogno, insieme a una raccolta di allegati (che contengono solo due campi, dai nostri dati, struttura ben appiattita).

Perché si deve fare questo?

  1. Semplifica il risultato di appiattire solo i campi che voglio veramente.

  2. I miei dati sono ora al sicuro incapsulati in una classe che può essere passato in giro senza paura di accidentalmente aggiornato i miei dati (che potrebbe accadere se si passa solo indietro NH entità di dati).

  3. Infine (e soprattutto), perché il codice di cui sopra solo genera un'istruzione SELECT.Avevo bloccato con il mio originale Criteri di query, avrebbe generato una di SELEZIONARE per ogni riga, e più per i bambini più ulteriormente giù la catena.Va bene se si tratta di piccoli numeri, ma se sei potenzialmente restituzione di migliaia di righe (come in questo caso - si tratta di un servizio web di posta elettronica del motore).

Spero che questo è stato utile per tutti coloro che desiderano spingere un po ' più in NHibernate l'esecuzione di query.Personalmente sono felice ora posso andare avanti con la mia vita!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top