如何在其他给定的 Guid 列表中的 Queryable 之上执行 OrderBy

Dil*_*d K 2 c# linq entity-framework-core dynamic-linq-core

我有搜索服务,它将为我提供具有正确顺序的实体的指南列表。例如,我的搜索服务给了我这个结果:

// Assuming you have a list of Guids named 'guidList'
List<Guid> guidList = new List<Guid>
{
    Guid.NewGuid(),
    Guid.NewGuid(),
    Guid.NewGuid()
};
Run Code Online (Sandbox Code Playgroud)

现在,我需要对数据库进行查询以获取这些实体:

using (var context = new YourDbContext())
{
    var students = context.Students
        .Where(e => guidList.Contains(e.Guid));
}
Run Code Online (Sandbox Code Playgroud)

我想以与 guidList 相同的顺序获取我的实体。执行 AsEnumerable 在这里不起作用,因为我将在最后添加另一个查询,这可能会影响性能

Svy*_*liv 5

这是通用函数,它通过以下方式动态生成表达式树:

query.OrderByDescending(e =>
      e.SomeProp == itemList[0] ? 0
    : e.SomeProp == itemList[1] ? 1
    : e.SomeProp == itemList[2] ? 2
    ... itemList.Count);
Run Code Online (Sandbox Code Playgroud)

您的情况的用法很简单:

context.Students
    .Where(e => guidList.Contains(e.Guid))
    .OrderByItems(e => e.Guid, guidList);
Run Code Online (Sandbox Code Playgroud)

及实施:

public static class QueryableExtensions
{
    public static IQueryable<T> OrderByItems<T, TItem>(this IQueryable<T> query, Expression<Func<T, TItem>> prop, IEnumerable<TItem> items)
    {
        var conditions = items
            .Select(item => Expression.Equal(prop.Body, Expression.Constant(item, typeof(TItem))))
            .ToList();

        // nothing to sort
        if (conditions.Count == 0)
            return query;

        Expression orderExpr = Expression.Constant(conditions.Count);

        for (var i = conditions.Count - 1; i >= 0; i--)
        {
            var condition = conditions[i];
            orderExpr = Expression.Condition(condition, Expression.Constant(i), orderExpr);
        }

        var entityParam = prop.Parameters[0];
        var orderLambda = Expression.Lambda<Func<T, int>>(orderExpr, entityParam);

        return query.OrderByDescending(orderLambda);
    }
}
Run Code Online (Sandbox Code Playgroud)