我已经在我的通用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名称。
但我不确定反射是这里最大的问题,有时,_previousEntries会容纳多达80万件物品。
_previousEntries在存储库类的类构造函数中将其项分配给它。_PKName还根据T的类型在类构造函数中分配一个值。
如果我只是在Single()语句上设置了一个断点,它可以处理2-3秒,所以我不知道如何确定这里的瓶颈是什么:对80万项的反射或单个().在5000条商品清单上,它的速度确实要快得多。
有什么意见吗?我能做些什么来优化我的列表吗?
发布于 2012-11-27 21:49:29
提供主键访问器作为委托。
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);发布于 2012-11-27 21:42:08
您可以将反射移出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);发布于 2012-11-27 21:42:55
无法快速搜索未排序的列表。这将是O(项目数).
您需要使用其他一些数据结构来更快地查找--字典或按PK排序的列表是可能的选择。
https://stackoverflow.com/questions/13593494
复制相似问题