2013-01-05 65 views
0

假设我在搜索表中输入条目时遇到性能问题。我们举个例子:EF 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.Local != null) { 
    output = AList.Local.SingleOrDefault(x=>x.xyz==xyz); 
    } 

    return output ?? AList.SingleOrDefault(x=>x.xyz==xyz); 

} 

} 

方法FindA首先在本地集合中查找,如果没有匹配,它将转到数据库。我需要这种方法来避免重复插入元素。

这种方法的问题很简单:对AList.Local的搜索具有O(n)复杂性,在我的情况下,AList.Local通常大于100,000条记录。如果AList.Local是一个在xyz属性上索引的字典,那就太好了;然而,EF Code First IDbSet使用ObservableCollection,根本没有索引。

一种可能的解决方案是将字典保留为AList.Local的镜像。但是,这很棘手,因为对AList.Local的更改不容易追踪。

另一种解决方案是使xyz属性成为主键并使用AList.Find(xyz)方法(我希望它是O(1)搜索,即使实体位于本地缓存中)。然而,我怀疑使用一个字符串作为主键会影响我的数据库的性能,并增加很多索引文件的大​​小。

谁能给我一个关于如何克服这种情况的建议?

+1

为什么更改'Local'集合不容易跟踪?它是'ObservableCollection',所以你可以很容易地订阅它的'CollectionChanged'事件并且被通知所有的改变。 –

+0

另外,如果您的本地图中有100k项,那么您可能会遇到麻烦,因为任何EF操作(例如添加单行)都将为O(N)。国际海事组织,你会好得多不跟踪这些与EF的实体,而是存储在散列表中最小的表示(如只是ID + xyz属性)。 –

回答

0

如果您关心实体框架的高性能,那么您需要禁用更改跟踪,并且不要使用LINQ或LINQ方法语法。更改跟踪是最大的麻烦制造者,并且使用传统循环代替LINQ的速度是,其速度是的两倍左右,但是我们只谈到在单个查找操作中减少了几毫秒的时间,但是却偏好LINQ上的传统循环。