2012-11-27 85 views
0

我已經在我的通用EF倉庫的Add()方法中實現了檢查我要插入的行是否已經存在於表中,如果存在,請使用當前可用的信息進行更新。List <>優化,有什麼可能?

private List<T> _previousEntries; 

//Try and find one with same PK in the temporary tables... 
var previousRow = _previousEntries.Single(n => (int)n.GetType().GetProperty(_PKName).GetValue(n, null) == entPKValue); 

//If we did find one... 
if (previousRow != null) 
{ 
    //Update the row... 
    return; 
} 

//Add it... 

所以我知道,我使用的反射,這是緩慢的,但我還沒有找到另一種方式,因爲不同的機構有不同的SQL PK的名字。

但我不知道反思是這裏最大的問題,有時,_previousEntries將容納80萬項。

_previousEntries在存儲庫類的類構造函數中將其項分配給它。 _PKName也根據T的類型在類構造函數中分配一個值。

如果我只在Single()語句中設置一個斷點,它肯定會處理2-3秒,所以我不會知道如何才能確定這裏的瓶頸是什麼:在800,000件物品上反射或Single()...在5000件物品清單中它肯定會更快。

有沒有意見?我能做些什麼來優化我的列表?

回答

1

提供一個主鍵訪問作爲代表

public class Repository<T> 
{ 
    private Funct<T,int> _getPK; 
    private Dictionary<int,T> _previousEntries; 

    public Repository(Funct<T,int> getPK) 
    { 
     _getPK = getPK; 
     _previousEntries = new Dictionary<int,T>(); 
    } 

    public void Add(T item) { 
     ... 
     int pk = _getPK(item); 
     T previousEntry; 
     if (_previousEntries.TryGetValue(pk, out previousEntry) { 
      // Update 
     } else { 
      // Add 
      _previousEntries.Add(pk, item); 
     } 
    } 
} 

你會創建這樣

var clientRepository = new Repositiory<Client>(c => c.ClientID); 
+0

接受的,因爲顯示的解釋和解決辦法回答一個repositiory如何使用。我還沒有實現這個詞典,但是這個,加上下面關於排序列表的建議,大大加快了速度。 –

2

你可以移動反射出來的LINQ語句,以避免它被反覆評估:

var property = typeof(T).GetProperty(_PKName); 
var previousRow = _previousEntries.Single(n => (int)property.GetValue(n, null) == entPKValue); 

或許傳遞Func<T, int>到類的構造函數和避免反射的需要完全。

private Func<T, int> _getKeyForItem; // Set by constructor 
... 
var previousRow = _previousEntries.Single(n => _getkeyForItem(n) == entPKValue); 
0

無法快速搜索未排序的列表。它將是O(項目數量)。

您需要使用其他一些數據結構來快速查找 - 按PK排序的字典或列表是可能的選項。

相關問題