2013-02-12 2 views
0

J'ai 3 tables dans ma DB qui je travaille:LINQ to Entities requête optimisation

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

Je dois changer UserTheme_AccessType pour tous UserTheme.Theme_ID dans le lieu de travail actuel avec ThemeWorkplace.Workplace_ID = 2 et utilisateur actuel avec User_ID = 1. Si le thème n'est pas une ligne UserTheme pour un tel utilisateur et un tel thème - je dois le créer.

j'ai écrit un tel code, mais il fonctionne trop longtemps:

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; 
    } 
} 

Je comprends que ce code accède trop de fois la base de données. Je veux trouver un moyen de se débarrasser de:

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

Dans chaque itération foreach. Quelqu'un pourrait m'aider s'il vous plaît?

Ajout de code de 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

Il peut être utile d'afficher les détails du fonctionnement de 'GetByUserTheme'. –

+0

Merci, j'ai ajouté l'instruction GetByUserTheme. –

Répondre

0

Première: Toutes les modifications pour les entités que vous avez fait dans le code seront poussés à la base de données en une seule commande par lots lorsque vous appelez context.SaveChanges. Donc, vous aurez une requête à la base de données pour sélectionner et une demande de mise à jour.

Mais dans votre commande batch, il y aura beaucoup de requêtes sql car EF génèrera sql pour les entités de mises à jour une par une (pas toutes en une).

Si vous souhaitez mettre à jour vraiment beaucoup d'enregistrements dans la base de données, vous devez utiliser le script sql (appelez la procédure stockée ou exécutez sqlquery) contre EntityFramework.

+0

Merci pour cette explication. Je pense qu'il est préférable pour moi d'étudier le travail de l'Entité pour comprendre comment tout cela fonctionne à l'intérieur. –

0

Je ne sais pas si je comprends tout à fait votre question et de la structure. Mais d'après ce que je vois, cela pourrait-il être une solution raisonnable?

Vous devez d'abord sélectionner les postes de travail dont l'ID est égal à 2. A partir de ce résultat, vous sélectionnez les ID de thème. Tous vos userthemes qui ont un themeID qui apparait dans le premier résultat seront alors sélectionnés dans 'userThemes'. À partir de là, vous parcourez les résultats et si l'ID utilisateur est vide, vous créez un UserTheme, sinon vous le mettez à jour.

Note rapide: le code ci-dessous n'est pas un vrai code de travail. Il est juste le code que j'ai écrit pour illustrer mon explication, une sorte de pseudo-code si vous voulez .. :)

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; 
}