将Func传递到Where并使用IQueryable

Jon*_*Jon 3 .net c# entity-framework

我正在使用Entity Framework并正在构建一个 IQueryable<T>

IQueryable<Message> query = db.Messages;

query = query.OrderByDescending(m => m.Created);
query = query.Where(m => m.Deleted == false);

if (lastTime != null)
    query = query.Where(m => m.Created < lastTime);

var func = ExpressionHelper.GetPredicate(stream);

query = query.Where(func).AsQueryable; *** ISSUE HERE?? ***

query = query.Skip(skip)
          .Take(count)
          .Include(m => m.Tags)
          .Include(m => m.Properties);

var results = query.ToList();
Run Code Online (Sandbox Code Playgroud)

问题是标签和属性未填入最终列表中.

我相信它与Func<>我传入的内容有关,并且相信在AsQueryable使用之后它虽然被使用但它不代表IQueryable或不再连接到数据库.

有没有办法填充标签和属性?

我不知道如果作出Func<>Expression<Func<>>有助于如果是这样,有没有办法转换下面是Expression<Func<>>

更新:

public static Func<Message, bool> GetPredicate(string expression)
{
    Func<Message, bool> result = null;

    try
    {
        ParameterExpression parameter = Expression.Parameter(typeof(Classes.Message), "Message");
        var lambda = DynamicExpression.ParseLambda(new[] { parameter }, null, expression);
        result = lambda.Compile() as Func<Message, bool>;
    }
    catch (Exception e)
    {
        Log.Fatal(e);
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 7

此时此处:

query.Where(func) // where func is Func<...>
Run Code Online (Sandbox Code Playgroud)

你已经切换到LINQ到对象.你不是之后做什么(在条件.Include等)是不相关的 -你不再撰写EF查询.你有一个薄IQueryable<T>的包装在LINQ到对象版本序列的,因为它是在该行,即

query = query.Where(func).AsQueryable(); // this is just a thing veneer over L2O
Run Code Online (Sandbox Code Playgroud)

切换到Expression<Func<...>>可能会有所帮助.

如果你绝对不能生成一个Expression,你可以在这一点之上移动Include等.

  • @Jon注意:这只是"如果你不能得到'表达式'"的解决方法.使用`Expression`谓词会更好(更高效,更少带宽等),以便可以组成完整的查询 (2认同)
  • EF内部必须能够将Expression <Func <>>分开,将其转换为SQL等价物; 使用Func <>是不可能的,它只是一个委托. (2认同)