2012-02-23 6 views
3

J'ai un cours de modèle, qui a plusieurs plusieurs à plusieurs relations comme l'âge ou le temps.plusieurs requêtes linq similaires

J'ai cette requête:

string IDs = "1,2,3" 
string[] IDList = IDs.Split(','); 

return (from x in entities.Course 
     where x.Ages.Where(val => IDList.Contains(val.ID.ToString())).Count() == IDList.Count() 
     select x); 

Et je dois régler la même requête pour le temps et plusieurs autres propriétés comme dans:

string IDs = "1,2,3" 
string[] IDList = IDs.Split(','); 

return (from x in entities.Course 
     where x.Times.Where(val => IDList.Contains(val.ID.ToString())).Count() == IDList.Count() 
     select x); 

Comment puis-je faire la requête plus dynamique, donc je n'avez pas plusieurs requêtes similaires?

Merci

+1

Est-ce juste Linq ou est-ce LINQ to Entities? La solution serait très différente. Pour Linq, utilisez simplement refactor dans une méthode. La solution Linq to Entities est à http://www.albahari.com/nutshell/linqkit.aspx –

Répondre

2

Vous pourriez faire une méthode qui accepte un Expression (depeneding sur votre type de données) et exécuter la requête de cette façon. Vous devrez faire votre Ages, Time, etc. implémenter une interface spécifique pour que cela fonctionne.

Par exemple, en supposant que vous utilisez EF et votre modèle est le code de la première utilisation DbSet s, vous pouvez faire ceci:

public interface IObject 
{ 
    int ID { get; set; } 
} 

public class Age : IObject 
{ 
    public int ID { get; set; } 

    // The rest of the data 
} 

public class Time : IObject 
{ 
    public int ID { get; set; } 

    // The rest of the data 
} 

public class Course 
{ 
    public virtual ICollection<Age> Ages { get; set; } 
    public virtual ICollection<Time> Times { get; set; } 
} 

public class CourseContext : DbContext 
{ 
    public DbSet<Course> Course { get; set; } 
} 

public class Test 
{ 
    public IQueryable<Course> GetCourses(Expression<Func<Course, ICollection<IObject>>> exp) 
    { 
     var entities = new CourseContext(); 
     string IDs = "1,2,3"; 
     string[] IDList = IDs.Split(','); 

     var c = exp.Compile(); 

     return entities.Course.Where(x => c.Invoke(x).Count(val => IDList.Contains(val.ID.ToString())) == IDList.Count()); 
    } 

    public void TestMethod() 
    { 
     var times = GetCourses(c => (ICollection<IObject>)c.Times); 
     var ages = GetCourses(c => (ICollection<IObject>)c.Ages); 
    } 
} 
+0

qui l'a fait - merci – user441365

+0

Pas de problème :) J'aime Expressions! Ils sont l'un de mes aspects préférés de C# –

1

Je fais des méthodes qui renvoient les différents résultats de la requête:

public IQuerable<Course> GetAllCourses() { 
    return entities.Course; 
} 

public IQueryable<Course> ByAge(IQueryable<Course> source, IEnumerable<String> ages { 
    return from x in source 
      where x.Ages.Where(val => ages.Contains(val.ID.ToString())).Count() == IDList.Count() 
      select x; 
} 

public IQuerable<Course> ByTimes(IQueryable<Course> source, IEnumerable<String> times) { 
    return from x in source 
      where x.Ages.Where(val => IDList.Contains(val.ID.ToString())).Count() == IDList.Count() 
      select x; 
} 

La raison en est que la méthode encapsule votre logique de requête - que la clause where est différente. Vous pouvez ensuite passer dans n'importe quelle source. Vous pouvez même combiner les deux filtres de requête comme un appel de méthode enchaînée:

var ids = new [] { "1", "2", "3" }; 
var coursesByAgeAndTime = ByTime(ByAge(GetAllCourses(), ids), ids); 
+0

bien oui c'est la même chose que j'ai obtenue - je me demandais s'il y avait un moyen d'encapsuler toute la requête dans 1 – user441365

+0

@ user441365 Les méthodes encapsulent la logique 'where'. Les instructions 'de x dans la source' et' select x' pourraient simplement avoir été 'source.Where (...)'. – Yuck

Questions connexes