2011-02-27 6 views
3

5 cadre, n'utilisant pas de relation clé étrangère dans la base de données, et je me demande comment 4.0 peut améliorer ce rebut de code dont j'ai besoin de repasser l'objet multiple après plusieurs jointures de tables.3.5 VS 4.0 .NET Framework

public IList<User> GetTutorByCourseId(int courseId) 
    { 
     IList<User> output = new List<User>(); 
     using (leDataContext db = new leDataContext()) 
     { 
      try 
      { 
       var m = from c in db.Courses 
         join ct in db.CourseByTutors on c.Id equals ct.CourseId 
         join u in db.Users on ct.TutorId equals u.Id 
         where c.Id == courseId 
         select new 
         { 
          c, ct, u 
         }; 

       foreach (var result in m) 
       { 
        User user = new User(); 
        user.Id = result.u.Id; 
        user.Name = result.u.Name; 
        user.CourseTutor.Id = result.ct.Id; 
        user.Course.Name = result.c.Name;  
        output.Add(user); 
       } 
       return output; 
      } 
      catch (Exception ex) 
      { 
       Logger.Error(typeof(User), ex.ToString()); 
       throw; 
      } 
     } 
    } 

Il y a 3 objets étant retour à l'appelant dans l'interface graphique. Cependant, pour ce faire, je dois ajouter la propriété de CourseByTutors public {get; set} et le cours public (get; set;) dans la classe User, ce qui, je le trouve, gâchera mon code. Dans ce cas, comment 4.0 serait capable de résoudre cela? J'ai lu quelque chose à propos de tupel select .. ??

+0

Vous pouvez sélectionner un tuple, ou au moins un type dynamique dans 3.5, AFAIK. –

+0

Pourriez-vous me montrer un exemple en convertissant mon code ci-dessus? Je suis en train de décider s'il faut convertir en 4.0 ou non .. – VeecoTech

Répondre

2

Même si vous n'avez pas de clés étrangères dans la base de données, il n'y a aucune raison de ne pas pouvoir ajouter de relations dans votre modèle EF. Cela aidera à simplifier le problème car vous n'aurez pas à générer de propriétés supplémentaires pour stocker les valeurs de votre enfant; CourseTutor, CourseName etc.

Les deux versions 3.5 et 4.0 peuvent vous aider, même si, selon mon expérience, c'est beaucoup plus facile dans 4.0.

Une fois que le code ci-dessus pourrait ressembler à:

var results = (from u in db.Users 
     where u.Course.Id == courseId 
     select u).ToList(); 
return results; 

Hope this helps.

+0

Je pense que garder les relations dans le modèle est la bonne chose à faire, mais cela ne résoudra pas vraiment le problème. Lorsque vous faites cela, vous obtenez tous les utilisateurs dans le cours, mais pour chaque utilisateur, vous obtenez tous leurs cours et tous les cours qu'ils enseignent. En ignorant qu'il n'y a probablement pas de relation de cours direct (par l'intermédiaire d'un tuteur, d'un instructeur ou d'un étudiant), pour chaque utilisateur, vous obtiendrez la collection de cours qu'ils enseignent, pas seulement le cours en question. Il n'est peut-être pas possible de déterminer quel cours présente un intérêt. Mieux vaut utiliser un modèle spécifique pour la vue, IMO. – tvanfosson

+0

Si vous renvoyez simplement les données en mode lecture seule, pourquoi ne pas envisager d'utiliser une procédure stockée pour aplatir la requête et vous renvoyer toutes les données dans une requête simple? Tout dépend où votre expérience est et quelle technologie vous êtes heureux de travailler avec. Si vous décidez d'utiliser des procédures stockées, vous avez quelques options; utilisez le framework d'entité (4.0 est beaucoup plus simple) consultez http://msdn.microsoft.com/en-us/library/bb896279.aspx ou créez un ensemble de données et ajoutez-y la procédure stockée. Ce dernier est une brise à faire mais peut-être présentera quelque chose d'autre à maintenir. – dubs

3

Qu'en est-il de ce point (en 3.5)?

select new User 
{ 
    Id = u.Id, 
    Name = u.Name, 
    CourseTutor = new CourseTutor {Id = ct.Id}, 
    Course = new Course {Name = c.Name} 
}; 
return m.ToList(); 

EDIT: Remplacée illégales CourseTutor.Name et Course.Id initializers. Le code corrigé fonctionnera, en supposant que le constructeur de User n'a pas fait d'initialisation fantaisie de CourseTutor et Course.

+1

+1. Incidemment, ReSharper fournira quelques conseils de refactoring vers des solutions similaires. – TrueWill

+0

merci pour la réponse rapide. Mais je ne pense pas que vous êtes en mesure de passer de cette façon puisque je repasse le IList ? J'ai reçu cette erreur 'Invalid initializer member declarator' sur CourseTutor.Id = ct.Id – VeecoTech

+0

@TrueWill: +1 pour promouvoir ReSharper. ;-) Cependant, je suis soudainement devenu incertain de savoir si c'est ce que le PO demandait vraiment; il semble qu'il soit plus intéressé par la suppression des propriétés supplémentaires sur 'User' ... –

0

La façon dont je traiterais normalement ceci est d'avoir un modèle séparé de mes entités de données pour l'interface graphique qui inclut juste les informations dont l'interface graphique a besoin. Vous pouvez le faire en 3.5 si vous le souhaitez.

public class TutorViewModel 
{ 
    public IEnumerable<User> Tutors { get; set; } 
    // the pair CourseId, UserId is the relation in CourseTutors so we only 
    // need to keep it once, not once per user. 
    public int CourseId { get; set; } 
    public string CourseName { get; set; } 
} 



public TutorViewModel GetTutorByCourseId(int courseId) 
{ 
    var model = new TutorViewModel { CourseId = courseId }; 

    using (leDataContext db = new leDataContext()) 
    { 
     try 
     { 
      model.CourseName = db.Courses 
           .First(c => c.CourseId == courseId) 
           .Name; 
      model.Users = db.CourseByTutors 
          .Where(c => c.Id == courseId) 
          .Join(db.Users, 
            c => c.TutorId, 
            u => u.Id, 
            (c,u) => u); 

      return model; 
     } 
     catch (Exception ex) 
     { 
      Logger.Error(typeof(User), ex.ToString()); 
      throw; 
     } 
    } 
} 
Questions connexes