2014-07-23 57 views
2

我有一個.Net後端,允許我通過相應的客戶端API通過其.Id和.Revision屬性查詢項目,甚至更好,批量通過提供這些組合的列表。最有效的方法來過濾包含(幾乎)在.Net中重複列表

However,每次.ID只能出現once per查詢,但該輸入does contain some入口使用同一個ID的多個次,然而,隨着different .Revision值,例如:

.Id | .Revision 
1 | 1 
1 | 2 
2 | 1 (unique .Id) 
3 | 3 
3 | 5 
4 | 2 (unique .Id) 
5 | 1 (unique .Id) 

。 。基本上,帶有.Id 1和3的條目會導致問題,我想知道以最有效的方式(即最少量的查詢)來檢索所有組合。

最壞的情況下,運行時明智,但最容易實現的方法是逐個檢索所有組合,忽略潛在的批量/批處理機制,但即使這將邏輯上返回正確的一組項目,但顯然很慢。

我將如何獲得最大的unqiue .Id/.Revision組合,並將剩餘的多個.Id-ones組合在一起,從而以最少的批量進行組合。

+0

什麼的底層技術LINQ是映射? –

+0

@CapTec沒有用於查詢後端的Linq提供程序,查詢之前的對象是純內存類型和自定義類型,基本上客戶端API僅爲int,[.Id和.Revision值。因此,在批量最少的情況下批量處理內存,在本地進行。 –

+0

您可以從唯一標識符中生成一棵樹,每個分支下的每個修訂版都有節點。這樣,您可以在每個節點需要時查詢您的api。 (認爲​​以說話的方式流式傳輸您的查詢)。雖然我可能會誤解你的問題。我已經完成了與XML類似的操作,以便在運行內存時保持其內存佔用低,同一個主體可能用於查詢API。 –

回答

2

你應該可以在一個循環中用幾個LINQ表達式相對容易地做到這一點。

例如,假設你有一個Item類是這樣的:

public class Item 
{ 
    public int Id { get; set; } 
    public int Rev { get; set; } 
} 

而且人的名單:要在批量查詢List<Item> Items;。在一批中,不會出現Id多次。

您可以Distinct很容易得到的第一個查詢:

var queryItems = Items.Distinct(new ItemIdComparer()).ToList(); 

和你比較器:

public class ItemIdComparer: IEqualityComparer<Item> 
{ 
    public int Equals(Item x, Item y) 
    { 
     return x.Id == y.Id; 
    } 

    public int GetHashCode(Item x) 
    { 
     return x.Id; 
    } 
} 

但是現在你需要那些遺留下來的物品。對於這一點,你需要一個相等比較,是以修訂進去,太:

public class ItemComparer: IEqualityComparer<Item> 
{ 
    public int Equals(Item x, Item y) 
    { 
     return x.Id == y.Id && x.Rev == y.Rev; 
    } 

    public int GetHashCode(Item x) 
    { 
     // not the best hash code, but should work okay. 
     return x.Id^x.Rev; 
    } 
} 

並獲得了在原來的列表中,但不是在不同的列表中,你叫Enumerable.Except的項目清單:

var leftover = Items.Except(queryItems, new ItemComparer()).ToList(); 

如果你把它放在一個循環,你可以這樣做反覆,直到leftover列表爲空:

var workingItems = Items.ToList(); 
while (workingItems.Count > 0) 
{ 
    var queryItems = workingItems.Distinct(new ItemIdComparer()).ToList(); 
    var leftover = workingItems.Except(queryItems, new ItemComparer()).ToList(); 
    DoQuery(queryItems); 
    workingItems = leftover; 
} 

使用這種算法,可以Ø只需兩次查詢即可獲得所有物品的信息。第一個會得到項目1.1,2.1,3.3,4.2和5.1。第二個查詢將得到1.2和3.5。

+0

'GetHashCode'應該可能是'x.Id^x.Rev',而不是'x.Id^y.Id'。 – porges

+0

@Porges:謝謝。固定。 –

+0

不錯,謝謝@JimMischel - 簡單而優雅! –

1

鑑於這種格式的條目列表:

public class Entry 
{ 
    public int Id { get; set; } 
    public int Version { get; set; } 
} 

如何憑身份證分組,然後用投影的ID,版本元素和職級標記爲批號每個條目的一個新的列表?排名將在所有具有相同Id的條目中進行。然後,您可以將具有相同批號的所有條目分組並一次提交一批。

這裏是我的表達:

var entries = GenerateEntries(); 

    var result = entries 
     .GroupBy(e => e.Id) 
     //project new entries with a batch number 
     .SelectMany(g => g.Select((e, i) => new { Id = e.Id, Version = e.Version, Batch = i })) 
     .GroupBy(e => e.Batch); 
+0

雖然這會起作用,但需要4個單獨的查詢來獲取其示例中項目的信息。它可以在兩個。 –

+0

我不關注這將如何導致更多的數據庫查詢。你能解釋一下嗎?在執行任何查詢之前,所有這些邏輯都在他的內存列表中進行操作。 – gerrard00

+0

我寫了一個快速的應用程序來仔細檢查,並導致兩批。第一個有1.1,2.1,3.3,4.2和5.1。第二批有1.2和3.5。與你的代碼不一樣嗎? – gerrard00

相關問題