Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net EF Code First-搜索具有特定属性值的特定行-性能_.net_Entity Framework_Entity Framework 4_Code First - Fatal编程技术网

.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属性)。