2011-05-30 80 views
0

我正在使用LINQ2SQL在SQL(精簡版)數據庫中搜索一堆int32。LINQ2SQL選擇基於大的行

我的主要問題是我有一個int32的大列表(數千),我想要DB中的所有記錄,其中的數據庫中的id字段與我的任何int32匹配。目前我正在選擇一行,有效地搜索索引數千次。

我該如何優化?臨時表?

+0

向我們展示您當前正在使用的LINQ查詢。 – RedFilter 2011-05-30 19:25:07

+1

你從哪裏得到這個int32的列表? – Francisco 2011-05-30 19:45:46

+0

我從複雜和絕密的事情中得到int32的列表。有關係嗎?;)它是查找圖片中某些關鍵點的算法的輸出。 – 2011-05-31 05:06:18

回答

0

插入您的整數的SQL表然後執行:

var items = from row in table 
      join intRow in intTable on row.TheIntColumn equals intRow.IntColumn 
      select row; 

編輯1 & 2:更改答案,所以他加入2個表,沒有任何收藏。

+1

你不能加入Linq2Sql的列表 – Magnus 2011-05-30 19:44:36

+0

那麼我會再次編輯我的答案,說他必須做我編輯過的東西,如果他想使用這個解決方案;-) – Tipx 2011-05-30 19:49:54

+0

在本頁嘗試了其他技巧。這是迄今爲止最快的。 – 2011-07-14 06:02:47

1

這聽起來像是你可以使用一個包含查詢:

int[] intArray = ...; 
var matches = from item in context.SomeTable 
       where intArray.Contains(item.id) 
       select item; 
+2

這對超過2000個值不起作用 - SQl日誌中出現嚴重錯誤。 – cjk 2011-05-30 19:34:06

+0

@ck有什麼樣的錯誤? – Magnus 2011-05-30 19:35:47

+0

不要使用SQL,而是執行超過一定數量參數的查詢。 – cjk 2011-05-30 19:38:05

1

對於serarching幾千年的價值觀,你的選擇是:

  • 發送XML塊存儲過程(複雜的,但可行)
  • 創建臨時表,批量上傳數據,然後加入到它(可能導致併發問題)
  • 執行multip查詢(即打破你的ID羣成千塊左右,並使用BrokenGlass的解決方案)

我不確定你可以使用精簡版。

0

我的偏好是爲搜索寫一個存儲過程。如果您正在搜索的字段上有一個索引,那麼當將要處理的行數增加時,它將使您的生活更輕鬆。

您將遇到的複雜性是編寫一個select語句,可以從輸入參數中執行IN子句。你需要的是有一個Table-Valued函數來將字符串(Id的)轉換成一個列並在IN子句中使用該列。 like:

Select * 
From SomeTable So 
Where So.ID In (Select Column1 From dbo.StringToTable(InputIds)) 
0

我已經厭倦了編寫手動批處理代碼後想出了這個linq解決方案。 這並不完美(即批次不完美),但它解決了問題。 當您不允許編寫存儲過程或sql函數時非常有用。幾乎每一個linq表達式都適用。

享受:

public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, int batchSize, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery) 
    { 
     return RunQueryWithBatching(listToBatch, initialQuery, batchSize); 
    } 

    public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery) 
    { 
     return RunQueryWithBatching(listToBatch, initialQuery, 0); 
    } 

    public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery, int batchSize) 
    { 
     if (listToBatch == null) 
      throw new ArgumentNullException("listToBatch"); 

     if (initialQuery == null) 
      throw new ArgumentNullException("initialQuery"); 

     if (batchSize <= 0) 
      batchSize = 1000; 

     int batchCount = (listToBatch.Count/batchSize) + 1; 

     var batchGroup = listToBatch.AsQueryable().Select((elem, index) => new { GroupKey = index % batchCount, BatchElement = elem }); // Enumerable.Range(0, listToBatch.Count).Zip(listToBatch, (first, second) => new { GroupKey = first, BatchElement = second }); 

     var keysBatchGroup = from obj in batchGroup 
            group obj by obj.GroupKey into grouped 
            select grouped; 

     var groupedBatches = keysBatchGroup.Select(key => key.Select((group) => group.BatchElement)); 

     var map = from employeekeysBatchGroup in groupedBatches 
        let batchResult = initialQuery(employeekeysBatchGroup.ToList()).ToList() // force to memory because of stupid translation error in linq2sql 
        from br in batchResult 
        select br; 

     return map; 
    } 

用法:

using (var context = new SourceDataContext()) 
{ 
    // some code 
    var myBatchResult = intArray.RunQueryWithBatching(batch => from v1 in context.Table where batch.Contains(v1.IntProperty) select v1, 2000); 
    // some other code that makes use of myBatchResult 
} 

然後要麼使用效果,無論是擴大列出,或任何你需要的。只要確保你不會丟失DataContext參考。