Nel mio modello di Customer
, ho
public virtual ICollection<AddressModel> AddressIDs { get; set; }
che fa riferimento a AddressModel
per darmi una relazione uno-a-molti tra i clienti e i loro indirizzi.
Ho una funzione di ricerca che utilizza
var CustomerList = _context.Customers
.Where(ps => ps.Surname.Contains(surnameToSearchFor))
per limitare il set di dati restituito per cognome.
Sto cercando di aggiungere la possibilità di cercare i codici postali nell'indirizzo. Seguendo vari collegamenti, questo funziona in Visual Studio ma si interrompe sull'esecuzione
CustomerList = CustomerList
.Include(ps => ps.AddressIDs
.Where(a => a.Postcode == postcodeToSearchFor));
con l'errore
InvalidOperationException: The property expression 'ps => {from AddressModel a in ps.AddressIDs where ([a].Postcode == __p_0) select [a]}' is not valid. The expression should represent a property access: 't => t.MyProperty
Come aggiungo una clausola Where
al mio LINQ sul sottotitolo?
Modifica A chi ha suggerito la clausola WHERE Multipla in Linq come risposta, questa domanda è chiaramente relativa a una singola tabella, mentre io ho chiesto chiaramente di sottomettere.
Non è possibile utilizzare dove dichiarazione in Includi. Puoi ottenere ciò che vuoi con la query single linq in questo modo:
var CustomerList = _context.Customers.Where(ps =>
ps.Surname.Contains(surnameToSearchFor)
&& ps.AddressIDs.Any(ad => ad.Postcode == postcodeToSearchFor ));
Come già menzionato nell'altra risposta (di Progressive), non puoi filtrare su Include
.
L'altra risposta (di Progressive) potrebbe essere una soluzione per te o potrebbe non esserlo. Ti darà tutti i clienti che hanno almeno un indirizzo nel codice postale , ma poi caricherà tutti gli indirizzi del cliente (compresi quelli con un codice postale diverso).
Questa risposta è scritta nel caso in cui desideri solo recuperare gli indirizzi per il codice postale, che sospetto sia il caso. Se desideri solo recuperare i clienti e filtrare solo i loro indirizzi (ma non caricare gli indirizzi), l'altra risposta (di Progressive) è la soluzione.
Come ho detto, non è possibile farlo tramite un'inclusione. Tuttavia, ci sono altre soluzioni:
1. Cerca gli indirizzi e includi i clienti.
Invece di cercare i clienti e includere i loro indirizzi.
var addresses = _context.Addresses
.Include(a => a.Customer)
.Where(a =>
a.Postcode == postcodeToSearchFor
&&
a.Customer.Surname.Contains(surnameToSearchFor))
.ToList();
Puoi comunque ottenere un elenco di clienti in questo modo:
var customer = addresses.Select(a => a.Customer).Distinct();
Come regola generale, avvia sempre la tua query dal bambino e includi i suoi genitori, non viceversa. Non importa in alcuni casi, ma nel tuo caso particolare, importa quanto vuoi evitare di caricare implicitamente tutti i bambini.
2. Definisci in modo esplicito il tuo set di risultati
In altre parole, utilizzare un Select()
.
Questo ti dà un maggiore controllo nel caso in cui tu abbia aspettative veramente specifiche sul risultato, ma è più dettagliato e (imo) non buono come l'altra soluzione. Usalo solo se la prima soluzione non funziona per te.
_context.Customers.Where(ps =>
ps.Surname.Contains(surnameToSearchFor)
&&
ps.AddressIDs.Any(ad => ad.Postcode == postcodeToSearchFor))
.Select(ps => new
{
Customer = ps,
Addresses = ps.AddressIDs.Where(ad => ad.Postcode == postcodeToSearchFor))
})
.ToList();
Si noti che non è necessario Include()
qui. Include()
configura il comportamento di caricamento implicito, ma Select()
carica i dati in modo esplicito.