2013-02-12 3 views
0

У меня есть 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 = 2 и текущим пользователем с User_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. –

+0

Спасибо, я добавил оператор GetByUserTheme. –

ответ

0

Первого: Все изменения для объектов, которые вы сделали в коде будут выталкиваться в базу данных в команде один пакетной когда вы звоните context.SaveChanges. Таким образом, у вас будет один запрос к базе данных для выбора и один запрос на обновление.

Но в вашей пакетной команде будет много запросов sql для причины EF генерировать sql для обновления объектов один за другим (не все в одном).

Если вы хотите обновить очень много записей в базе данных, вы должны использовать sql-скрипт (вызвать хранимую процедуру или выполнить sqlquery) против использования EntityFramework.

+0

Благодарим вас за это объяснение. Я считаю, что мне лучше изучить Entity freamework, чтобы понять, как все это работает глубоко внутри. –

0

Я не знаю, если я полностью понять ваш вопрос и структуру. Но на основании того, что я вижу, может ли это быть разумным?

Сначала вы выбираете рабочие места с идентификатором, равным 2. Из этого результата вы выбираете идентификаторы темы. Все ваши userthemes, которые имеют идентификатор темы, который встречается в первом результате, затем будут выбраны в «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; 
} 
Смежные вопросы