.net EF Code First-搜索具有特定属性值的特定行-性能
假设在表中搜索条目时出现性能问题。让我们来看一个例子:.net EF Code First-搜索具有特定属性值的特定行-性能,.net,entity-framework,entity-framework-4,code-first,.net,Entity Framework,Entity Framework 4,Code First,假设在表中搜索条目时出现性能问题。让我们来看一个例子: public class A { [Key] public int Id {get;set;} public string xyz {get; set;} } public class Context : DbContext { public DbSet<A> AList {get;set;} public A FindA(string xyz) { A output = null; if(AList.Lo
public class A {
[Key]
public int Id {get;set;}
public string xyz {get; set;}
}
public class Context : DbContext {
public DbSet<A> AList {get;set;}
public A FindA(string xyz) {
A output = null;
if(AList.Local != null) {
output = AList.Local.SingleOrDefault(x=>x.xyz==xyz);
}
return output ?? AList.SingleOrDefault(x=>x.xyz==xyz);
}
}
公共A类{
[关键]
公共int Id{get;set;}
公共字符串xyz{get;set;}
}
公共类上下文:DbContext{
公共数据库集{get;set;}
公共A FindA(字符串xyz){
A输出=null;
如果(AList.Local!=null){
输出=AList.Local.SingleOrDefault(x=>x.xyz==xyz);
}
返回输出??AList.SingleOrDefault(x=>x.xyz==xyz);
}
}
FindA方法首先在本地集合中查找,如果没有匹配项,则转到数据库。我需要这种方法来避免重复插入元素
这种方法的问题很简单:对AList.Local的搜索有O(n)复杂度,在我的例子中,AList.Local通常大于100000条记录。如果AList.Local是一个基于xyz属性索引的字典,那就太好了;但是,EF Code First IDbSet使用一个完全没有索引的ObservableCollection
一个可能的解决方案是维护字典作为AList.Local的镜像。然而,这很棘手,因为对AList.Local的更改不容易跟踪
另一个解决方案是将xyz属性作为主键,并使用AList.Find(xyz)方法(我希望这是一个O(1)搜索,即使实体位于本地缓存中)。但是,我怀疑使用字符串作为主键会影响数据库的性能,并会大大增加索引文件的大小
有谁能给我一个如何克服这种情况的建议吗?如果您关心实体框架的高性能,那么您需要禁用更改跟踪,并且不要使用LINQ或LINQ方法语法。更改跟踪是一个大麻烦,使用传统循环而不是LINQ大约快2倍,但我们说的是,在使用传统循环而不是LINQ时,单个查找操作只需减少毫秒。为什么对
本地
集合的更改不容易跟踪?它是observateCollection
,因此您可以轻松订阅它的CollectionChanged
事件,并了解所有更改。此外,如果您的本地图形中有100k项,您可能会遇到麻烦,因为任何对此的EF操作(例如添加一行)都将是O(N)。在我看来,最好不要使用EF跟踪这些实体,而是在哈希表中存储一个最小的表示(例如ID+xyz属性)。