Linq To SQL:使用.Contains时保留列表顺序

时间:2010-12-30 23:01:57

标签: .net linq-to-sql sql-order-by

我正在使用Lucene.net构建一个MyListOfIds As List(Of Integer),然后我将其传递给我的Linq服务。然后我按如下方式搜索数据库

Return _EventRepository.Read().Where(Function(e) MyListOfIds.Contains(e.ID)).ToList

现在我知道Lucene已根据每个学期的重量排序MyListOfIds。令人痛苦的是Linq在SQL搜索中失去了这个顺序。

我的问题:如何在构建Lambda表达式时保留该排序顺序?

我尝试使用LINQPad来查看查询是如何构建的,但是因为我必须声明变量LINQPad并没有向我显示结果SQL: - (

这是我在LINQPad

中尝试过的内容
Dim i As New List(Of Integer)
i.Add(1)
i.Add(100)
i.Add(15)
i.Add(3)
i.Add(123)

Dim r = (From e In Events
         Where i.Contains(e.ID)
         Select e)

注意:我的示例是在VB.NET中,但我不介意回复是否在C#

5 个答案:

答案 0 :(得分:2)

我会说LINQ to SQL查询会以数据库的自然顺序(可能是主键?)返回数据,因为SQL中的IN条件(.Contains应该是ORDER翻译为)没有指定任何IComparer<T>,你的LINQ表达也没有。如果您将其视为普通的SQL语句,很明显您无法轻松地以这种方式指定顺序。

为了对加载的数据进行排序,您可以将其取消排序,然后按照Lucene的已知顺序对枚举进行排序。您可能必须自己编写(即客户{{1}})。

答案 1 :(得分:2)

从L2S查询中获取无序结果,然后使用the .Select overload that gives ordinal position以与L2O(linq-to-objects)查询中的List相同的顺序重新排序。 E.g:

var someResult = _EventRepository.Read().Where(e => MyListOfIds.Contains(e.ID)).ToList();

var someResultOrdered =
  from sr in someResult
  join lid in MyListOfIds.Select((v, i) => new { v, i }) on sr.ID equals lid.v
  orderby lid.i
  select sr;

答案 2 :(得分:2)

正如我提到的那样,我认为Dictionary方法是可行的方法。我会这样做:

Public Function GetLuceneSearchResults(ByVal ids As List(Of Integer)) As List(Of Domain.Event) Implements IEventService.GetLuceneSearchResults
    Dim Results = (From e In _EventRepository.Read()
                   Where ids.Contains(e.ID)
                   Select e).ToDictionary(Function(e) e.ID, Function(e) e)

    Return (From i In ids
            Where Results.ContainsKey(i)
            Select Results(i)).ToList()
End Function

第一个查询返回一个以事件id为键的Dictionary,并将事件本身作为值。您可以通过这种方式获得哈希查找的性能优势。

答案 3 :(得分:1)

你可能需要一个IDictionary,你的密钥只是一个增量(如一个标识列)和你Lucene实际id的值。

然后,在您的LINQ2SQL语句中,而不是执行此“where”子句,您可以使用数据库中的列在“字典值”中执行“连接”。在LINQ中,按字典键排序。

编辑:添加示例

以下是一个例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {

            var ids = new Dictionary<int, int>();

            //key is just a sort sequence, value is the ID from Lucene
            ids.Add(1, 27);
            ids.Add(2, 25);
            ids.Add(3, 29);

            var ctx = new DataClasses1DataContext();

            var tabs = (from t in ctx.Tabs
                         where ids.Values.Contains(t.TabID)
                         select t).ToList();


            var sorted = from t in tabs
                         join id in ids on t.TabID equals id.Value
                         orderby id.Key
                         select t;

            foreach (var sortedItem in sorted) {
                Console.WriteLine(sortedItem.TabID);
            }
            Console.ReadLine();


        }
    }

}

答案 4 :(得分:1)

OP回答

我认为@hangy让我思考正确的思路。这就是我想出来的......

愿意接受建议!

    Public Function GetLuceneSearchResults(ByVal ids As List(Of Integer)) As List(Of Domain.Event) Implements IEventService.GetLuceneSearchResults
        Dim Results = _EventRepository.Read().Where(Function(e) ids.Contains(e.ID)).AsQueryable
        Dim Output As New List(Of Domain.Event)

        For Each i In ids
            Output.Add(Results.Where(Function(e) e.ID = i).SingleOrDefault)
        Next

        Return Output
    End Function

现在抛开性能推测,这肯定与预期完全一致。我很想听听你对性能提升的看法,或者这只是出去吃午饭的方式。感谢。