如何以自定义ID顺序从表中获取记录?

时间:2016-09-06 12:48:35

标签: c# entity-framework linq

我在下面的变量中有一些Ids存储:

List<int> Ids;

现在我想根据上面的ID获取记录,但是上面的顺序与Ids.

相同

例如:记录在数据库中是这样的:

员工:

Id
1
2
3
4
5

现在,如果Ids数组保存这样的ID: 4,2,5,3,1 ,那么我只是按此顺序获取记录:

查询:

  var data = context.Employee.Where(t => Ids.Contains(t.Id)).ToList();

但是上面的查询给出的输出就像它在表格中一样:

Id
1
2
3
4
5

预期输出:

Id
4
2
5
3
1

更新:我已经尝试过以下解决方案,但由于这是实体框架,因此无法解决问题:

var data = context.Employee.Where(t => Ids.Contains(t.Id))
                    .OrderBy(d => Ids.IndexOf(d.Id)).ToList();

要使上述解决方案正常工作,我必须添加到列表中:

var data = context.Employee.Where(t => Ids.Contains(t.Id)).ToList()
                    .OrderBy(d => Ids.IndexOf(d.Id)).ToList();

但我不想在内存中加载数据,然后过滤掉我的记录。

2 个答案:

答案 0 :(得分:1)

如果没有存储过程,您可以使用属于规范函数的Union?: 我无法想象其他方式。

<强>:吗
您可以使用它为每个id值分配一个weigth,然后按weigth排序。此外,您必须生成?:using dynamic linq。

What is the equivalent of "CASE WHEN THEN" (T-SQL) with Entity Framework?
Dynamically generate LINQ queries

<强>联盟
我认为这是获得它的更简单的方法。在这种情况下,您可以为每个Id添加Where / Union。

编辑1
关于使用Union,您可以使用与此类似的代码

IQueryable<Foo> query = context.Foos.AsQueryable();
List<int> Ids = new List<int>();
Ids.AddRange(new[] {3,2,1});
bool first = true;
foreach (int id in Ids)
{
    if (first)
    {
        query = query.Where(_ => _.FooId == id);
        first = false;
    }
    else
    {
        query = query.Union(context.Foos.Where(_ => _.FooId == id));
    }
}


var results = query.ToList();

这会生成跟随查询

SELECT
[Distinct2].[C1] AS [C1]
FROM ( SELECT DISTINCT
        [UnionAll2].[C1] AS [C1]
        FROM  (SELECT
                [Distinct1].[C1] AS [C1]
                FROM ( SELECT DISTINCT
                        [UnionAll1].[FooId] AS [C1]
                        FROM  (SELECT
                                [Extent1].[FooId] AS [FooId]
                                FROM [Foos] AS [Extent1]
                                WHERE [Extent1].[FooId] = @p__linq__0
                        UNION ALL
                                SELECT
                                [Extent2].[FooId] AS [FooId]
                                FROM [Foos] AS [Extent2]
                                WHERE [Extent2].[FooId] = @p__linq__1) AS [UnionAll1]
                )  AS [Distinct1]
        UNION ALL
                SELECT
                [Extent3].[FooId] AS [FooId]
                FROM [Foos] AS [Extent3]
                WHERE [Extent3].[FooId] = @p__linq__2) AS [UnionAll2]
)  AS [Distinct2]
p__linq__0 = 3
p__linq__1 = 2
p__linq__2 = 1

编辑2
我认为最好的方法是在内存方法中,因为它具有相同的网络负载,EF不会生成丑陋的查询,这些查询无法在与SQL Server不同的数据库上运行,代码更具可读性。在您的特定应用程序中可能是union /哪里更好。所以,通常我会建议你尝试一下内存方法,如果你有[性能]问题,你可以检查一下是否更好。

答案 1 :(得分:1)

由于当您未指定ORDER BY plot command时返回数据的顺序,您必须添加ORDER BY以指示您希望如何排序。不幸的是,您必须根据内存中的对象/值进行排序,并且不能在SQL查询中使用它进行排序。

因此,您可以做的最好的事情是在从数据库中检索数据后订购内存。

var data = context.Employee
    // Add a criteria that we only want the known ids
    .Where(t => Ids.Contains(t.Id))
    // Anything after this is done in-memory instead of by the database
    .AsEnumerable()
    // Sort the results, in-memory
    .OrderBy(d => Ids.IndexOf(d.Id))
    // Materialize into a list
    .ToList();