2010-05-12 7 views
4

J'ai la requête suivante:Création d'une requête LINQ dynamique

from p in dataContext.Repository<IPerson>() 
    join spp1 in dataContext.Repository<ISportsPerPerson>() on p.Id equals spp1.PersonId 
    join s1 in dataContext.Repository<ISports>() on spp1.SportsId equals s1.Id 
    join spp2 in dataContext.Repository<ISportsPerPerson>() on p.Id equals spp2.PersonId 
    join s2 in dataContext.Repository<ISports>() on spp2.SportsId equals s2.Id 
    where s1.Name == "Soccer" && s2.Name == "Tennis" 
    select new { p.Id }; 

Il sélectionne toute la personne qui joue au football et le tennis.
Lors de l'exécution, l'utilisateur peut sélectionner d'autres variables à ajouter à la requête, par exemple: "Hockey". maintenant ma question est, comment pourrais-je ajouter dynamiquement "Hockey" à la requête? Si « Hockey » est ajouté à la requête, il ressemblerait à ceci:

from p in dataContext.Repository<IPerson>() 
    join spp1 in dataContext.Repository<ISportsPerPerson>() on p.Id equals spp1.PersonId 
    join s1 in dataContext.Repository<ISports>() on spp1.SportsId equals s1.Id 
    join spp2 in dataContext.Repository<ISportsPerPerson>() on p.Id equals spp2.PersonId 
    join s2 in dataContext.Repository<ISports>() on spp2.SportsId equals s2.Id 
    join spp3 in dataContext.Repository<ISportsPerPerson>() on p.Id equals spp3.PersonId 
    join s3 in dataContext.Repository<ISports>() on spp3.SportsId equals s3.Id 
    where s1.Name == "Soccer" && s2.Name == "Tennis" && s3.Name == "Hockey" 
    select new { p.Id }; 

Il serait préférable que la requête est construit dynamiquement comme:

private void queryTagBuilder(List<string> tags) 
{ 
    IDataContext dataContext = new LinqToSqlContext(new L2S.DataContext()); 
    foreach(string tag in tags) 
    { 
     //Build the query? 
    } 
} 

Toute personne a une idée sur la façon de régler cela correctement? Merci d'avance!

+0

Dupliquer? http://stackoverflow.com/questions/2712337/passing-a-where-clause-for-a-linq-to-sql-query-as-a-parameter/2712795 – Steven

Répondre

2

Moi et mon collègue ont trouvé la solution, et nous refondus la requête afin qu'il fonctionnerait correctement. Nous utilisons maintenant la requête suivante pour récupérer le jeu de résultats correct:

var query = dataContext.Repository<ILead>(); 

     foreach (var tag in tags) 
     { 
      String tagName = tag; 
      query = query.Where(l => dataContext.Repository<ISportsPerPerson>() 
         .Any(tpl => tpl.PersonId.Equals(l.Id) && tpl.Sports.Name.Equals(tagName))); 
     } 
// Do something with query resultset :] 
3

Une requête LINQ n'est pas analysée tant qu'elle n'est pas réellement exécutée. Donc, vous pouvez faire des choses comme ceci:

var q = from r in ctx.records 
     /* Do other stuff */ 
     select r; 

if (!string.IsNullOrEmpty(search)) { 
    q = from r in q 
     where r.title == search 
     select r; 
} 

if (orderByName) { 
    q = q.OrderBy(r => r.name); 
} 

/* etc */ 

Ceci créera une instruction SQL en cours d'exécution.

Pour votre question spécifique: Les jointures compliquent quelque peu la tâche, mais je pense que vous pouvez vous joindre à d'autres requêtes "dynamiques".

Vous finiriez avec quelque chose comme ceci:

var baseQ = from p in dataContext.Repository<IPerson>() 
      select p; 
foreach(var tag in tags) { 
    baseQ = from p in baseQ 
    join spp1 in dataContext.Repository<ISportsPerPerson>() on p.Id equals spp1.PersonId 
    join s1 in dataContext.Repository<ISports>() on spp1.SportsId equals s1.Id 
    where s1.name == tag 
    select p; 
} 

/* If you have defined your relations correct, simplify to something like this. 
    Does not actually work because of SportsPerPerson probably has multiple sports: */ 
foreach(var tag in tags) { 
    baseQ = baseQ.Any(p => p.SportsPerPerson.Sports.Name == tag); 
} 


var resultQ = from p in baseQ 
    select new { p.Id }; 
+0

Apparaît promesse:] va essayer! – Bas

Questions connexes