2009-08-07 9 views
0

Disons que j'ai une classe PersonSummary, qui combine les propriétés (colonnes) de 2 tables de base de données Person et Address (avec une clé étrangère de Person), ainsi un PersonSummary a un prénom, un état et un zip.Sélection dynamique dans LINQ

La création de PersonSummary pourrait être dans une clause select avec (personne, adresse => new PersonSummary {personne, adresse})

Ma couche d'accès aux données n'a pas connaissance de PersonSummary, donc j'aimerais ajoutez la clause select à un niveau supérieur et ne construisez que le from, où, etc. à un niveau inférieur, pour sélectionner des lignes à partir de la personne et de l'adresse en fonction de différents critères, par exemple: avoir des méthodes comme GetFemales() ou GetPeopleInAState().

Des recommandations sur comment faire cela? Est-ce que mes fonctions d'accès aux données renvoient des expressions et la méthode de niveau supérieur se contente d'une clause Select?

Signatures/types de retour les plus appréciés.

Répondre

0

Lorsque vous utilisez les méthodes d'extension sous-jacente utilise LINQ, vous pouvez faire à peu près tout ce que vous voulez.

Alors als que votre couche de données renvoie des informations IQueryable, on pourrait dire

var withSummary = db.GetFemales() 
        .Select(p => new PersonSummary(p, p.Address)); 

Si vous utilisez SQL ou LINQ EF, toutes les données sont extraites à l'aide d'une seule requête. Toutefois, si votre fournisseur de LINQ est moins avancé, vous pouvez essayer

var withSummary = db.GetFemales().AsEnumerable() 
        .Select(p => new PersonSummary(p, p.Address)); 

Mais cela ne nécessite que vous précharger en quelque sorte (ou charge paresseux) l'adresse.

1

Vous pouvez simplement ajouter des extensions à IQueryable:

public static IQuearyable<Person> Famales(IQueryable<Person> this entry) 
{ 
    return entry.Where(p => p.Gender == Gender.Female); 
} 

public static IQuearyable<Person> LivingInState(IQueryable<Person> this entry, State state) 
{ 
    return entry.Where(p => p.State == state); 
} 

public static IQuearyable<Person> PeopleWithAddress(IQueryable<Person> this entry) 
{ 
    return entry.Where(p => p.Address != null); 
} 

// Use like this 
var marriedFemales = GetPersonsQuery().Females().Where(f => f.IsMarried) 
var femaleVictorians = GetPersonsQuery().Females().LivingInState(State.Victoria) 
var femaleVictorians = GetPersonsQuery().PeopleWithAddress() 
    .Females().Where(x => x.IsMarried) 
    .Select(x => new { x.LastName, x.Address}) 
+0

merci, c'est un bon début. Maintenant, est-ce que je peux encore scinder le GetPersonQuery() afin que je puisse avoir le from et les jointures dans la couche de données et la sélection/projection dans la couche de gestion? Une façon consiste à définir une entité PersonAddress dans la couche de données qui aura la personne et l'adresse, mais je voudrais éviter cela. Ainsi, par exemple, Écrire une méthode PeopleWithAddresses() (je ne sais pas quel type de retour ce serait), et avoir var marriedFemales = PeopleWithAddresses(). Femelles(). Où (f => f.IsMarried) .Sélectionner new {Person. LastName, Address.State)} ou simplement .Select Person.Age –

+0

Vous pouvez facilement le faire. Je vais mettre à jour la réponse avec un autre échantillon. –

Questions connexes