2009-10-20 10 views
0

C'est facile à faire en SQL et j'ai beaucoup de mal à le faire en utilisant Linq to SQL. J'ai deux entités configuration, projet et ProjectsbyUser:Comment filtrer une entité basée sur une autre entité? Linq many-to-many en C#

[Table(Name = "Projects")] 
public class Project 
{ 
    [Column(IsPrimaryKey = true, IsDbGenerated = true, Name="Job")] 
    public string ProjectId { get; set; } 
    [Column(Name = "Description")] 
    public string Description { get; set; }   

    [Association(OtherKey = "ProjectId")] 
    private EntitySet<ProjectList> _projectlist = new EntitySet<ProjectList>(); 
    public IEnumerable<ProjectList> ProjectList { get { return _projectlist; } } 
} 

[Table(Name = "ProjectLists")] 
public class ProjectList 
{ 
    [Column(IsPrimaryKey = true)] 
    public string UserId { get; set; } 
    [Column(IsPrimaryKey = true)] 
    public string ProjectId { get; set; } 
} 

Donc, dans mon ProjectsController je vais avoir ceci:

public ViewResult myProject() 
    { 
     var query = projectsRepository.Projects 
         .Where(x => x.ProjectId == "H1000").ToList(); 
     return View(query.ToList()); 
    } 

Et hé, qu'est-ce que vous savez, il affichera tous les utilisateurs attachés à projet H1000 avec quelques belles déclarations foreach imbriquées dans ma vue. Aussi facile que possible, mais j'essaie de filtrer en fonction de l'utilisateur. Je peux obtenir l'utilisateur assez facile (User.Identity.Name.ToString() qui correspond à la colonne UserId). Cela doit être facile à faire, mais je ne suis pas en train de trouver un moyen de l'accomplir sans écrire un code terrible. Cette blog post explique ce que je veux faire, mais il semble utiliser le modèle "Linq to SQL classes" et maintenant mes entités sont assis dans de beaux fichiers de classe C# et non dans les fichiers de concepteur de GUI VS2008 fantaisie. Il doit y avoir une manière élégante de résoudre ceci, j'ai travaillé dessus pendant environ une semaine et pense que je pourrais m'être couru dans un coin. Merci de votre aide!

Répondre

0

Est-ce que c'est ce dont vous avez besoin?

projectsRepository.Projects 
    .Where(x1 => x1.ProjectId == "H1000" && 
     x1.ProjectList.Any(x2 => x2.UserId == User.Identity.Name.ToString())) 
    .ToList() 
1

Side note: vous faites ToList() deux fois, ce qui est nécessaire :)

Réponse à votre question:

Créer une association mère entre Projectlist et projet, de sorte que chaque L'élément ProjectList a une propriété appelée "Project" (ou ce que vous voulez appeler).

Ensuite, il suffit de faire:

string userId = User.Identity.Name.ToString(); 
var query = projectsRepository.ProjectLists.Where(pl => pl.UserId == userId).Select(pl => pl.Project); 

... et bam, vous avez une liste des projets pour cet utilisateur.

EDIT: l'autre solution postée qui fonctionne sur la relation enfant fonctionnera aussi, mais à mon avis c'est plus propre et si vous profilez la requête, c'est en fait plus efficace. L'autre solution finit par faire des jointures coûteuses en interne.

0
string userID = User.Identity.Name.ToString(); 
var query = from p in repository.Projects 
     from pl in p.ProjectList 
     where pl.UserID = userID 
     select p; 

Peut-être que cette façon est la plus lisible.

0

Je pense que j'ai posé la question en tant qu'utilisateur non enregistré et que je n'arrive pas à me connecter et à marquer correctement la meilleure réponse. Pour la postérité, la méthode de Mike Maryonwski a fonctionné magnifiquement et a évité les jointures inutiles que j'essayais d'éviter. Le code que j'ajouté à l'entité myproject:

[Association(ThisKey = "ProjectId")] 
public Project Project { get; set; } 

Selon SQL Profiler il fonctionne de façon très efficace, tirant uniquement ce qui est nécessaire (que je suppose est en quelque sorte le point, mais je suis toujours étonné de voir qu'il ne générer une déclaration TSQL désordonnée). La méthode de Misha semble avoir fonctionné, mais je préfère l'expression et le style de Lambda par rapport à l'instruction "SQL inversé". Cela me semble si mauvais, mais j'ai écrit TSQL pour toujours.

Questions connexes