2013-07-10 71 views
27

我有以下方法自動地從支架模板與儲存庫生成的相同查詢中使用.Find()&.INCLUDE(): -

public Group Find(int id) 
{ 
    return context.Groups.Find(id); 
} 

但由於組對象具有兩個導航屬性我所需要的,所以我想包括.Include,所以我.where更換.find: -

public Group Find(int id) 
{ 
    return context.Groups.Where(c=>c.GroupID==id) 
         .Include(a => a.UserGroups) 
         .Include(a2 => a2.SecurityRoles) 
         .SingleOrDefault(); 
} 

但我的問題是如何應用.Include.find()而不是使用的?

+2

您可以通過將過濾器傳遞給單個調用並刪除where子句(例如'.SingleOrDefault(c => c.GroupID == id)' –

+0

)來簡化甚至更多.Where和.Find之間有什麼區別? ? –

+1

在這裏查看where和find之間的區別,http://msdn.microsoft.com/en-us/data/jj573936.aspx,基本上只找到按鍵搜索,並有一個微妙的優化,如果您以前查詢過該實體。這是優化實際上是你不能使用包括 –

回答

34

我只是在考慮實際發現的內容。 @lazyberezovsky是正確的包括和發現不能用於彼此聯合。我認爲這是相當故意和這裏的原因:

上DbSet查找方法使用的主鍵值來試圖找到 上下文追蹤的實體。如果在 上下文中未找到實體,則將查詢發送到數據庫以在那裏查找實體 。如果在數據庫中的上下文或 中未找到實體,則返回空值。

找到的是從兩個顯著方式使用查詢不同:

  • ,往返到數據庫中,如果與給定鍵的實體未在上下文中找到纔會進行。
  • 查找將返回處於已添加狀態的實體。也就是說,查找將返回已添加到上下文但尚未保存到數據庫中的實體。

(從http://msdn.microsoft.com/en-us/data/jj573936.aspx

因爲發現是一個優化的方法,可避免需要前往服務器。如果您已經跟蹤實體,這很好,因爲EF可以更快地返回它。但是,如果它不只是我們之後的這個實體(例如我們想要包含一些額外的數據),那麼就無法知道這個數據是否已經從服務器上加載。雖然EF可能會與連接一起進行優化,但它會對數據庫狀態作出假設,因此很容易出錯。

我想包括和發現不能夠一起使用是一個非常慎重的決定,以確保數據的完整性和不必要的複雜性。當你想要進行連接時,它總是要去數據庫來執行連接,這是更簡潔,更簡潔的 。

+0

,但找到處於「已添加」狀態但尚未添加到數據庫的對象的想法很可怕並且可能導致不一致的結果,您認爲如何? –

+0

@johnG是的我同意它有點奇怪,我不是100%的規則,但它可能是這隻適用於手動定義鍵的實體。如果它與具有自動生成密鑰的實體一起工作,那麼當你真正將它們添加到數據庫中時,它們實際上不會獲得您認爲它的密鑰。在任何情況下,我的個人偏好總是使用.SingleOrDefault或.FirstOrDefault來查找數據庫中的實體 –

6

你不行。 Find方法在DbSet<T>類型上定義並返回實體。您不能在實體上致電Include,因此唯一可能的選擇是在Include之後調用Find。你需要DbSet<T>類型爲,但Include("UserGroups")將返回DbQuery<T>,並Include(g => g.UserGroups)也將返回DbQuery<T>

public static IQueryable<T> Include<T>(this IQueryable<T> source, string path) 
    where T: class 
{ 
    RuntimeFailureMethods.Requires(source != null, null, "source != null"); 
    DbQuery<T> query = source as DbQuery<T>; 
    if (query != null)  
     return query.Include(path); // your case 
    // ... 
} 

DbQuery<T>不是DbSet<T>從而方法Find不可用一個孩子。同時請記住,Find首先在本地對象中查找實體。如果它們尚未加載,它將如何包含一些引用的實體?

+3

在那個筆記,即時通訊不是一個巨大的粉絲無論如何,.FirstOrDefault()或.SingleOrDefault()履行類似的目的和工作任何IEnumerable –

+1

另一點是在使用Entity Frameork時考慮.. –

+0

@LukeMcGregor我相信First()和類似的東西總會碰到數據庫。 – Chazt3n