2016-09-06 40 views
1

我有一些Ids店在以下变量:如何根据ID的自定义顺序从表中获取记录?

List<int> Ids; 

现在我想基于以上的ID,但与同样为了得到记录,因为它是在上述Ids.

对于如:记录是这样的数据库:

员工:

Id 
1 
2 
3 
4 
5 

现在,如果IDS数组保存IDS是这样的: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(); 

但我不想在内存中加载数据,然后筛选出我的记录。

任何人可以帮助我实现这一目标?

+0

你也需要一些努力。请阅读[问]并分享你的研究。这个问题之前已经被问过很多次了,例如参见[duplicate](http://stackoverflow.com/questions/15275269/sort-a-list-from-another-list-ids)。 – CodeCaster

+0

@CodeCaster我找不到Ids.so的Indexof方法这个问题是如何为你重复的? –

+0

@CodeCaster Indexof方法不会为实体框架工作,所以在盲目地将问题标记为重复之前,请仔细阅读问题。谢谢 –

回答

1

由于当您未指定ORDER BY时返回数据的顺序为not determined,因此您必须添加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(); 
+0

非常感谢你Maarten先生的热心帮助。请继续帮助像这样:) –

1

没有存储过程,你可以使用Union?:这都是典型的功能。
我不能想象其他方式。


你可以用它来分配weigth每个值id然后由weigth顺序。另外,你必须生成?:使用动态linq。

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

联盟
我想这是更简单的方法来获得它。在这种情况下,您可以为每个ID添加一个位置/联盟。

编辑1
关于使用联盟您可以使用类似的代码这

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(); 

这产生followiong查询

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 

EDIT 2
我觉得的最好的方法是在记忆方法b由于它具有相同的网络负载,因此EF不会生成丑陋的查询,该查询无法在与SQL Server不同的数据库上工作,并且代码更具可读性。在你的特定应用中可能是工会/哪里更好。所以,通常我会建议你尝试记忆方法,然后,如果你有[性能]问题,你可以检查联盟/哪里更好。

+0

你能提供任何关于如何在这种情况下使用联合来达到预期结果的例子吗? –

+0

参见上面的编辑。 – bubi

+0

我真的很感谢你的回答,这就是为什么我有upvoted,但唯一的问题是哪种方法会更好。在内存方法或你的方法? –

相关问题