2012-02-23 8 views
3

У меня есть модель курса, в которой есть несколько многих и многих отношений, таких как Age или Time.несколько похожих запросов linq

У меня есть этот запрос:

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); 

И мне нужно установить один и тот же запрос для времени и несколько других свойств, как в:

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); 

Как я могу сделать запрос более динамичным, так что я не имеют нескольких похожих запросов?

Благодаря

+1

Это просто Linq или это Linq для лиц? Решение будет сильно отличаться. Для Linq просто используйте рефактор в метод. Решение Linq to Entities находится по адресу http://www.albahari.com/nutshell/linqkit.aspx –

ответ

2

Вы могли бы сделать метод, который принимает Expression (depeneding от типа данных) и выполнить запрос таким образом. Вам нужно будет сделать свой Ages, Time и т. Д. Реализовать определенный интерфейс для его работы.

Например, если предположить, что вы используете EF и ваша модель Code First с помощью DbSet с, вы могли бы сделать это:

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

, который сделал это - спасибо – user441365

+0

No prob :) Я люблю выражения! Это один из моих любимых аспектов C# –

1

Я бы сделать методы, которые возвращают различные результаты запроса:

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; 
} 

Причина заключается в том, что метод инкапсулирует логику запроса - только пункт where отличается. Затем вы можете передать любой источник. Можно даже объединить два фильтра запроса в виде цепочки вызова метода:

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

ну да, это то же самое, что я получил - мне было интересно, есть ли способ инкапсулировать весь запрос в 1 – user441365

+0

@ user441365 Методы инкапсулируют логику 'where'. Операторы 'from x in source' и' select x' могут просто быть «source.Where (...)». – Yuck

Смежные вопросы