简体   繁体   English

常规 LINQ 方法链接中间的表达式树; 动态和可空类型?

[英]Expression trees in middle of regular LINQ method chaining; dynamic and nullable types?

I'm trying to write a dynamic query but having trouble when dealing with dynamic types in the OrderBy section of my query.我正在尝试编写动态查询,但在处理查询的 OrderBy 部分中的动态类型时遇到问题。 I've seen some solutions using method call expressions, which may work for me, but I don't know how to fit that into my existing code where I am using method chaining on either side.我已经看到一些使用方法调用表达式的解决方案,这可能对我有用,但我不知道如何将其融入我现有的代码中,我在任一端都使用方法链接。 It's possible I can just use dynamic as my type but I don't think that will work with Nullable types.我可以只使用 dynamic 作为我的类型,但我认为这不适用于 Nullable 类型。

public async Task<IEnumerable<MyEntityModel>> GetEntities(QueryEntityResource request)
{
    IQueryable<MyEntityModel> queryableData = ...;
    Expression whereLambdaExp = ...;

    queryableData = queryableData.Where(whereLambdaExp);

    ParameterExpression param = Expression.Parameter(typeof(MyEntityModel));
    PropertyInfo property = typeof(MyEntityModel).GetProperty(request.sortModel.ColId);
    Expression propExpr = Expression.Property(param, property);
    var lambdaExpression = Expression.Lambda<Func<MyEntityModel, dynamic>>(propExpr , new ParameterExpression[] { param }); // can't use dynamic

    // Errors here; can't use dynamic type in lambda expression -- Need to specify types
    if (request.sortModel.Sort == "asc")
    {
        queryableData = queryableData.OrderBy(lambdaExpression);
    }
    if (request.sortModel.Sort == "desc")
    {
        queryableData = queryableData.OrderByDescending(lambdaExpression);
    }

    queryableData = queryableData.Skip(request.StartRow).Take(request.EndRow - request.StartRow);

    return queryableData.ToListAsync();
}

If I use dynamic it won't work with my nullable types:如果我使用动态,它将不适用于我的可为空类型:

System.ArgumentException: Expression of type 'System.Nullable`1[System.Int32]' cannot be used for return type 'System.Object' System.ArgumentException:“System.Nullable`1[System.Int32]”类型的表达式不能用于返回类型“System.Object”

This is untested;这是未经测试的; but I think it is close to what you need (I feel like I've written this code before... also, see this answer ):但我认为它接近你所需要的(我觉得我以前写过这段代码......另外,请参阅这个答案):

You can build calls to OrderBy instantiated to the types you need and then build a new IQueryable .您可以构建对OrderBy的调用,实例化为您需要的类型,然后构建一个新的IQueryable My method removes the async as I couldn't build a quick test for that in LINQPad.我的方法删除了async ,因为我无法在 LINQPad 中为它构建快速测试。

public IEnumerable<MyEntityModel> GetEntities(QueryEntityResource request) {
    IQueryable<MyEntityModel> queryableData = default;
    Expression<Func<MyEntityModel, bool>> whereLambdaExp = default;

    queryableData = queryableData.Where(whereLambdaExp);

    var param = Expression.Parameter(typeof(MyEntityModel));
    var propExpr = Expression.Property(param, request.sortModel.ColId);
    var lambdaExpression = Expression.Lambda(propExpr, param);

    if (request.sortModel.Sort == "asc" || request.sortModel.Sort == "desc")
        queryableData = queryableData.Provider.CreateQuery<MyEntityModel>(Expression.Call(typeof(Queryable), request.sortModel.Sort == "asc" ? "OrderBy" : "OrderByDescending",
                        new[] { typeof(MyEntityModel), propExpr.Type }, queryableData.Expression, Expression.Quote(lambdaExpression)));

    queryableData = queryableData.Skip(request.StartRow).Take(request.EndRow - request.StartRow);

    return queryableData.ToList();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM