我已经在我的通用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件物品清单上肯定会更快。
有什么意见吗?有什么我可以做的来优化我的列表吗?
答案 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排序的词典或列表是可能的选项。