Posso interrogare un UserType con diverse proprietà mappate su una singola colonna?

StackOverflow https://stackoverflow.com/questions/5845693

  •  27-10-2019
  •  | 
  •  

Domanda

Ho il seguente modello di dominio:

public class Name
{
    private readonly string fullName;
    public Name(string fullName) { this.fullName = fullName }
    public string FullName { get { return fullName; } }
    public string FirstName { get { /* ... */ } }
    public string MiddleNames { get { /* ... */ } }
    public string LastName { get { /* ... */ } }
    public static implicit operator Name(string name) { /* ... */ }
}

public class Person
{
    public Name BirthName { get; set; }
    public Name Pseudonym { get; set; }
}

Ho implementato IUserType così posso mappare ciascun nome su una singola colonna del database con il nome completo.

Domande come questa funzionano:

var people = session.QueryOver<Person>()
                    .Where(p => p.Name == "John Doe")
                    .List();

Ma non posso interrogare in questo modo:

var people = session.QueryOver<Person>()
                    .Where(p => p.Name.LastName == "Doe")
                    .List();

Posso far funzionare NHibernate con questo?

È stato utile?

Soluzione

Non sono molto un utente NHibernate, ma analizzando tutte le informazioni che abbiamo qui sullo scenario, ho la forte sensazione che la risposta sia che non puoi.

Stai mappando il valore contenuto in quella classe a un unico valore nel DB.

Per consentire di interrogare sui suoi pezzi, dovrebbe capire come tutte quelle informazioni secondarie nella classe di nome siano correlate all'intero valore.

Ciò significherebbe capire cosa sta facendo il codice C# personalizzato.


Aggiornamento 1:

La risposta di cui sopra riguarda la generazione automatica per te e l'utilizzo della query esatta che hai menzionato lì.

Puoi sicuramente aggirare il problema come suggerito da @CS. Cioè, definire una funzione definita dall'utente che fa quello che vuoi e mappandola in NHibernate.

Per lo meno che ti permetterà di fare qualcosa come:

session.QueryOver<Person>()
        .Where(p => session.PersonLastName(p) == "Doe")
        .List();

Un altro modo sarebbe quello di definire un metodo di estensione che viene tradotto in ciò che desideri, implementandolo come in questo articolo: http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html

L'uso sarebbe quindi come:

 session.QueryOver<Person>()
     .Where(p=> p.Name.LastNameExt() == "Doe")// Ext just to avoid name collision
     .List();

Infine, non sono sicuro che sia possibile mappare le proprietà secondarie alle funzioni definite dall'utente per ciascuno, in modo che la tua query possa rimanere invariata come:

 session.QueryOver<Person>()
                .Where(p => p.Name.LastName == "Doe")
                .List();

Non che in tutti i casi tu stia cambiando dalla concatenazione di dati a dati di analisi. Sei l'unico a sapere se questo ti sta davvero acquistando qualcosa, rispetto a mantenere le proprietà separatamente.

Altri suggerimenti

Credo che sia possibile, ma richiederà un po 'di lavoro sul lato SQL delle cose. La prima cosa che probabilmente proverei è creare un UDF di qualche tipo che dividerà il nome per te e farà il confronto necessario. Puoi quindi estendere Nhibernate per mappare a questo UDF e tu dovrebbe Essere in grado di invocare questa funzione dalla tua query, che si tratti di SQL, HQL o ICRITERIA.

Sarai in grado di interrogare solo il nome completo, a causa del fatto che è solo un campo di database.

Se lo mappini in modo diverso in modo che FirstName e LastName siano colonne separate dovresti essere in grado di interrogare ciascuno di essi, ma potresti quindi avere difficoltà a interrogare su una proprietà chiamata FullName.

È necessario creare colonne calcolate. Saranno di sola lettura ma puoi interrogare contro di loro. Vedere qui.

Quello che potresti fare è implementare il tuo wrapper di repository per questi oggetti e implementare metodi come GetUsersByLastName() che potrebbero utilizzare HQL per eseguire questi tipi di query di "ricerca per valore parziale".

Qualcosa di simile al seguente dovrebbe consentirti di effettuare la ricerca in base a qualsiasi valore parziale a condizione che tu passi la stringa di ricerca corretta:

var hql = "select p from People p where lower(p.BirthName) like :searchText";

Modificare:

Rimosso Cognome dalla query.Il modo in cui funzionerebbe è utilizzare il testo di ricerca ancorato all'inizio o alla fine del campo BirthName.Ad esempio, se volessi cercare tutte le persone con il cognome Smith, potresti fare:

var hql = "select p from People p where lower(p.BirthName) like '% smith'";

E nel caso delle persone con il nome Joe:

var hql = "select p from People p where lower(p.BirthName) like 'joe %'";
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top