2013-01-05 93 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上的傳統循環。