2013-02-12 76 views
0

我在DB 3個表內,以我的工作:LINQ到實體查詢優化

  1. Theme [Theme_ID]
  2. ThemeWorkplace [Theme_ID, Workplace_ID, ThemeWorkplace_ID]
  3. UserTheme [User_ID, Theme_ID, UserTheme_ID, UserTheme_AccessType]

我需要改變UserTheme_AccessType所有UserTheme.Theme_ID在當前工作場所與ThemeWorkplace.Workplace_ID = 2User_ID = 1當前用戶。如果主題是UserTheme中沒有這樣的用戶和這樣的主題行 - 我需要創建它。

我寫了這樣的代碼,但它工作時間過長:

var themeList = (from t in m_Entities.Theme 
        where (from tw in m_Entities.ThemeWorkplace 
         where tw.Workplace.Workplace_ID == 2 
         select tw.Theme.Theme_ID).Contains(t.Theme_ID) 
          select t) 
       .ToList(); 

foreach (Theme theme in themeList) 
{ 
    var oldUserTheme = GetByUserTheme(user/*user is given*/, theme); 

    if (oldUserTheme == null) 
    { 
     /* create new User Theme with params, that I need*/ 
     this.Add(newUserTheme, true); 
    } 
    else 
    { 
     /* here - changing found row */ 
     oldUserTheme.UserTheme_AccessType = 2; 
    } 
} 

我明白,這段代碼訪問數據庫的次數太多。我想找到一種方法來擺脫:

var oldUserTheme = GetByUserTheme(user/*user is given*/, theme); 

在每foreach迭代。有人可以幫我嗎?

添加GetByUserTheme()的代碼:

private UserTheme GetByUserTheme(User user, Theme theme) 
{ 
    return m_Entities.UserTheme.FirstOrDefault(ut => ut.User.User_ID == user.User_ID && ut.Theme.Theme_ID == theme.Theme_ID); 
} 
+1

這可能是張貼的GetByUserTheme'如何'工作機制的細節是有用的。 – 2013-02-12 11:36:05

+0

謝謝,我已經添加了GetByUserTheme聲明。 – 2013-02-12 11:45:48

回答

0

第一:你在代碼中也做了實體的所有更改會在一個批處理命令推到數據庫當你撥打context.SaveChanges。所以你將有一個請求數據庫選擇和一個更新請求。

但在你的批處理命令,將成爲事業EF許多SQL查詢生成更新實體逐一SQL(而不是在一個所有)。

如果你想在數據庫中更新真的多條記錄,你應該使用SQL腳本(調用存儲過程或執行sqlquery的)反對使用的EntityFramework。

+0

感謝您的解釋。我認爲研究Entity freamework以瞭解它如何在內部深處起作用更好。 – 2013-02-12 13:40:07

0

我不知道如果我完全理解你的問題和結構。但基於我所看到的,這可能是一個合理的解決方案嗎?

首先,選擇具有ID等於2。從該結果對工作場所選擇的主題-ID的。然後,所有具有以前結果中出現的themeID的用戶將被選入'userThemes'。從那裏開始迭代結果,如果用戶標識爲空,則創建一個新的UserTheme,否則更新它。

快速注:以下的代碼是沒有真正的工作代碼。這只是代碼,我寫信給我舉例說明,那種僞代碼,如果你願意.. :)

var userThemes = entities.Userthemes 
         .Where(ut => entities.Workplaces 
               .Where(w => w.WorkPlaceID == 2) 
               .Select(s => s.ThemeID) 
               .Contains(ut.ThemeID)); 

foreach (UserTheme ut in userThemes) 
{ 
    if (ut.UserID.ToString() == "") 
    { 
     //Create 
    } 
    else 
     ut.UserThemeAccessType = 2; 
}