2010-08-27 3 views
1

J'ai répliqué une version allégée de mon code qui a été récemment réécrit pour utiliser linq pour accéder à la base de données. Cependant, à mon avis, le linq est vraiment simple et pourrait probablement être optimisé, en particulier autour de la ligne 90 où il y a une instruction linq dans une boucle foreach.Optimisation de l'utilisation simple de Linq en C#

Il serait vraiment utile de voir comment quelqu'un d'autre pourrait écrire cette tâche simple en utilisant linq. Merci d'avance! Voici un extrait de mon code source.

// Model objects - these are to be populated from the database, 
// which has identical fields and table names. 
public class Element 
{ 
    public Element() 
    { 
     Translations = new Collection<Translation>(); 
    } 

    public int Id { get; set; } 
    public string Name { get; set; } 
    public Collection<Translation> Translations { get; set; } 

    public class Translation 
    { 
     public int Id { get; set; } 
     public string Title { get; set; } 
     public string Content { get; set; } 
     public Language Lang { get; set; } 
    } 
} 
public class Language 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Code { get; set; } 
} 

// Stripped-down functions for adding and loading Element 
// objects to/from the database: 

public static class DatabaseLoader 
{ 
    // Add method isn't too bulky, but I'm sure it could be optimised somewhere. 
    public static void Add(string name, Collection<Translation> translations) 
    { 
     using (var db = DataContextFactory.Create<ElementContext>()) 
     { 
      var dbElement = new Database.Element() 
      { 
       Name = name 
      }; 
      db.Elements.InsertOnSubmit(dbElement); 
      // Must be submit so the dbElement gets it's Id set. 
      db.SubmitChanges(); 

      foreach (var translation in translations) 
      { 
       db.Translations.InsertOnSubmit(
        new Database.Translation() 
         { 
          FK_Element_Id = dbElement.Id, 
          FK_Language_Id = translation.Lang.Id, 
          Title = translation.Title, 
          Content = translation.Content 
         }); 
      } 

      // Submit all the changes outside the loop. 
      db.SubmitChanges(); 
     } 
    } 

    // This method is really bulky, and I'd like to see the many separate linq 
    // calls merged into one clever statement if possible (?). 
    public static Element Load(int id) 
    { 
     using (var db = DataContextFactory.Create<ElementContext>()) 
     { 
      // Get the database object of the relavent element. 
      var dbElement = 
       (from e in db.Elements 
       where e.Id == id 
       select e).Single(); 

      // Find all the translations for the current element. 
      var dbTranslations = 
       from t in db.Translations 
       where t.Fk_Element_Id == id 
       select t; 

      // This object will be used to buld the model object. 
      var trans = new Collection<Translation>(); 

      foreach (var translation in dbTranslations) 
      { 
       // Build up the 'trans' variable for passing to model object. 
       // Here there is a linq statement for EVERY itteration of the 
       // foreach loop... not good (?). 
       var dbLanguage = 
        (from l in db.Languages 
        where l.Id == translation.FK_Language_Id 
        select l).Single(); 

       trans.Add(new Translation() 
        { 
         Id = translation.Id, 
         Title = translation.Title, 
         Content = translation.Content, 
         Language = new Language() 
          { 
           Id = dbLanguage.Id, 
           Name = dbLanguage.Name, 
           Code = dbLanguage.Code 
          } 
        }); 
      } 

      // The model object is now build up from the database (finally). 
      return new Element() 
       { 
        Id = id, 
        Name = dbElement.Name, 
        Translations = trans 
       }; 
     } 
    } 
} 
+0

@SO: Nous avons besoin de ligne automatique de numérotation dans les échantillons de code .... –

+0

Coupez votre exemple de code vers le bas pour les quelques petits blocs que vous voulez des idées pour ce beaucoup de code le fait lire comme vous voulez juste que nous fassions votre refactor complet pour vous. –

+0

@Jimmy Hoffa: désolé de l'extrait de code long - Je pensais que vous montrer le contexte entier serait utile pour voir quel était mon problème - les instructions linq imbriquées ... mais croyez-moi, cela est massivement dépouillé de ce que le projet le code est vraiment. – Greg

Répondre

1

En utilisant certains constructeurs confectionnés à schématiser:

public static Element Load(int id) 
{ 
    using (var db = DataContextFactory.Create<ElementContext>()) 
    { 
     var translations = from t in db.Translations 
          where t.Fk_Element_Id == id 
          join l in db.Languages on t.FK_Language_Id equals l.Id 
          select new Translation(t, l); 

     return new Element(db.Elements.Where(x => x.Id == id).Single(), translations); 
    } 
} 
+0

C'est le genre de choses que j'espérais - je ne sais pas trop comment les expressions lambda fonctionnent, mais avec votre exemple j'espère que j'apprendrai plus vite. Merci! – Greg

0

La première chose que je n'aime pas ici toute la « nouvelle traduction() {} bla = bla parce qu'ils sont grands blocs de code, je les mettre dans une méthode où vous les remettez la objets et ils retournent la nouvelle pour vous.

Translations.InsertOnSubmit(CreateDatabaseTranslation(dbElement, translation)); 

et

trans.Add(CreateTranslationWithLanguage(translation, dbLanguage)); 

etc, où que vous avez du code comme celui-ci, il embrouille simplement la lisibilité de ce que vous faites ici.