列表与LT;>优化,有什么可能性?

时间:2012-11-27 21:35:04

标签: c# .net list

我已经在我的通用EF存储库的Add()方法中实现了检查我要插入的行是否已经存在于表中,如果存在,请使用当前可用的信息更新它。

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 最多可容纳800,000件物品。

_previousEntries 在存储库类的类构造函数中为其分配了项目。 _PKName还在类构造函数中赋值,具体取决于T的类型。

如果我只是在Single()语句中设置一个断点,它肯定会处理2-3秒,所以我不知道如何确定这里的瓶颈:反射或Single()在800,000物品......在5,000件物品清单上肯定会更快。

有什么意见吗?有什么我可以做的来优化我的列表吗?

3 个答案:

答案 0 :(得分: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);

答案 1 :(得分: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);

答案 2 :(得分:0)

无法快速搜索未排序的列表。它将是O(项目数)。

您需要使用其他一些数据结构来更快地查找 - 按PK排序的词典或列表是可能的选项。