如何将IQueryables组合成一个电话?

时间:2016-01-23 23:19:35

标签: c# entity-framework linq

我想将IQueryable作为参数传递给一个函数,然后调用实体框架提供程序执行查询,如下所示:

public ICollection<MyRowType> RunCommand(IQueryable<MyRowType> query)
{
    using (var db = new MyDbContext())
    {
        var result = db.MyRowType
            .Include(r => r.RelatedTableA)
            .Include(r => r.RelatedTableB)
            .Include(r => r.RelatedTableC)

            // How do I make the value in `query` run here?

            .ToList();
    }
}

我基本上将数据库调用包装到此方法以返回所有必需的包含但我不想失去通过IQueryable<MyRowType>进行自定义查询的灵活性。

以下是我想要实现的一个例子:

public ICollection<MyRowType> SomeOtherMethod(string id, SomeValue value = null, SomeOtherValue  otherValue = null)
{
    var query = Enumerable.Empty<MyRowType>()
        .Where(r => r.Id == di);

    if (value != null)
        query = query.Where(r => r.PropertyOne == value);

    if (otherValue != null)
        query = query.Where(r => r.PropertyTwo == otherValue);

    return RunCommand(query);     
}

回答更新:

我将Yacoub Massaddasblinkenlight的答案合并到这两种方法中:

public static ICollection<MyRowType> RunCommand(Expression<Func<MyRowType, bool>> condition)
{
    return Get(t => t.Where(condition));
}

public static ICollection<MyRowType> RunCommand(Func<IQueryable<MyRowType>, IQueryable<MyRowType>> query)
{
    using (var db = new DbContext())
    {
        var includes = db.MyRowType
            .Include(r => r.RelatedTableA)
            .Include(r => r.RelatedTableB)
            .Include(r => r.RelatedTableC)

        var result = query(includes)
            .ToList();

       return result;
    }
}

2 个答案:

答案 0 :(得分:1)

您应该通过<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body> <div id="background"> <div class="newItem"> <p> Add item </p> </div> </div> </body>代替Func<IQueryable<MyRowType>,IQueryable<MyRowType>>,如下所示:

IQueryable<MyRowType>

然后你可以像这样使用它:

public ICollection<MyRowType> RunCommand(Func<IQueryable<MyRowType>,IQueryable<MyRowType>> func)
{
    using (var db = new MyDbContext())
    {
        IQueryable<MyRowType> q = db.MyRowType
            .Include(r => r.RelatedTableA)
            .Include(r => r.RelatedTableB)
            .Include(r => r.RelatedTableC);

        var result = func(q);

        return result.List();
    }
}

或者使用其他类似的LINQ方法:

var result = RunCommand(q => q.Where(....));

请注意,您无法传递将选择与var result = RunCommand(q => q.Where(....).OrderBy(x => ...).Take(10)); 不同的类型的查询。如果你想要那么你可以使方法通用如下:

MyRowType

现在您可以像这样使用它:

public ICollection<T> RunCommand<T>(Func<IQueryable<MyRowType>,IQueryable<T>> func)
{
    using (var db = new MyDbContext())
    {
        IQueryable<MyRowType> q = db.MyRowType
            .Include(r => r.RelatedTableA)
            .Include(r => r.RelatedTableB)
            .Include(r => r.RelatedTableC);

        var result = func(q);

        return result.List();
    }
}

答案 1 :(得分:1)

IQueryable<T>中提取表达式并不容易,并且您无法直接应用传递给方法的queryable。但是,由于您似乎试图通过在不更改输出类型的情况下传递IQueryable<T>来限制查询,因此可能更容易将API更改为采用条件而不是IQueryable<T>,如下所示:< / p>

public ICollection<MyRowType> RunCommand(Expression<Func<MyRowType,bool>> condition) {
    using (var db = new MyDbContext()) {
        var result = db.MyRowType
            .Include(r => r.RelatedTableA)
            .Include(r => r.RelatedTableB)
            .Include(r => r.RelatedTableC)
            .Where(condition)
            .ToList();
    }
}

如果您使用LINQ to Entities predicate combiner,则可以将自定义条件与RunCommand方法中执行的常规准备步骤结合使用:

public ICollection<MyRowType> SomeOtherMethod(string id, SomeValue value = null, SomeOtherValue  otherValue = null) {
    Expression<Func<MyRowType,bool>> condition =
        r => r => r.Id == di;
    if (value != null)
        condition = condition.And(r => r.PropertyOne == value);
    if (otherValue != null)
        condition = condition.And(r => r.PropertyTwo == otherValue);
    return RunCommand(query);     
}