多个类似的linq查询

时间:2012-02-23 14:54:00

标签: .net linq entity-framework

我有一个模型课程,它有几个多对多的关系,如年龄或时间。

我有这个问题:

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

我需要为Time和其他几个属性设置相同的查询,如:

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

如何使查询更具动态性,以便我没有多个类似的查询?

由于

2 个答案:

答案 0 :(得分:2)

您可以创建一个接受Expression的方法(依赖于您的数据类型)并以这种方式运行查询。您需要让AgesTime等实现特定的界面才能生效。

例如,假设您使用EF并且您的模型使用DbSet s代码优先,您可以这样做:

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

答案 1 :(得分: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);