如何在Linq和Entity Framework中动态构建Select查询

3
我希望能够执行以下操作:
public async Task<List<dynamic>> searchEntities(string query, list<string> columnNames)
{
   var columNames = GetPropertiesUsingReflectionAndfilter<Entity>(columnNames);
   await db.entities.select(x => { columnNames }).where(...)..ToListAsync();
}

我需要在Controller中公开一个自定义的EF搜索方法。 我想提供部分响应。 在我使用的OData版本中,$search不可用。
也许可以使用IQueryable来实现这一点?
另一种方法是构建参数化SQL查询。 想知道是否有更好的方法使用EF和Linq? 谢谢。。
解决方案:
感谢@IvanStoev,最终我添加了一个库System.Linq.Dynamic(免费,拥有>100万次下载),以完成此操作。 现在我有...
using System.Linq.Dynamic;

            var columnNames = GetColumNames<Entity>(qry.TableList);
            var selector = "new(" + String.Join(", ", columnNames.ToArray()) + ")";

            var results = await db.Lessons
                .Where(x => x.LessonName.Contains(qry.Query) == true || x.HTML.Contains(qry.Query) == true)
                .Select(selector)
                .ToListAsync();

            return Ok(results);

简述. 我的情景下完整用法。

控制器:

[HttpPost, Route("Search/Lessons")]
public async Task<IHttpActionResult> SearchLessons([FromBody] SearchQuery qry)
{
    var columnNames = GetColumNames<Lesson>(qry.TableList);

    if (columnNames.Count < 1) {
        return BadRequest();
    }

    var selector = "new(" + String.Join(", ", columnNames.ToArray()) + ")";

    var results = await db.Lessons
        .Where(x => x.LessonName.Contains(qry.Query) == true || x.HTML.Contains(qry.Query) == true)
        .Select(selector)
        .ToListAsync();

    return Ok(results);
}

辅助函数:...

private List<string> GetColumNames<T>(List<string> columnsToFetch = null)
{
    var properties = GetProperties<T>();
    var columnNames = new List<string>();

    if (columnsToFetch == null)
    {
        return properties;
    }

    foreach (var columnRequested in columnsToFetch)
    {
        var matchedColumn = properties
            .Where(x => x.ToLower() == columnRequested.ToLower())
            .FirstOrDefault();

        if (matchedColumn != default(string))
        {
            columnNames.Add(matchedColumn);
        }
    }

    return columnNames;
}

而且...
private List<string> GetProperties<T>()
    {
        dynamic model = TypeDescriptor.GetProperties(Activator.CreateInstance<T>());

        List<string> result = new List<string>();
        foreach (var prop in model)
        {
            result.Add(prop.Name);
        }
        return result;
    }

2
请查看免费的包Dynamic LINQ - Ivan Stoev
@IvanStoev 你应该将它添加为一个可能的答案 :) - Dave 5709
2个回答

1

免责声明:我是项目Eval-Expression.NET的所有者。

这个库不是免费的,但允许您在运行时编译和执行C#代码。例如,您可以动态执行任何LINQ操作。

教程:LINQ Dynamic

例子:

public searchEntities(string query, list<string> columnNames)
{
   await db.entities.SelectDynamic(x => "{" + string.Join(",", columnNames) + "}")
           .where(...)..ToListAsync();
}

0

我不认为这是可能的。

首先,要从searchEntities返回列表,select需要创建一个命名对象。

你可以做的是将一个函数表达式传递给searchEntities。

public Task<List<T>>  searchEntities<T>(EXpression<Func<Entity, T> selector)
{
    return await db.entities.select(selector).where(...)..ToListAsync();
}


Expression<Func<Entity, AdHocClass1> selector1 = (Entity e)=> new AdHocClass1 {...};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接