2009-10-22 5 views
3

J'ai deux tables.Linq Join - Duplicates

Table 1.Users (nom d'utilisateur, Nom)

table 2.Picture (ID, nom d'utilisateur, IsPrimary)

Chaque utilisateur peut avoir zéro à de nombreuses images.

J'essaie d'écrire une requête qui retourner tous les utilisateurs (avec ou sans images) et une image unique Id (de l'image avec IsPrimary = true).

J'ai écrit cette requête Linq:

var v = from u in Users 
    join p in Photos on u.Username equals p.Username 
    select new 
    { 
    u.Username, 
    p.ID 
      }; 

Cela fonctionne mais retourne les lignes en double de l'utilisateur. (si l'utilisateur a plus d'une photo).

Je souhaite obtenir une ligne par utilisateur. Est-ce possible?

Répondre

4

Cela devrait faire exactement ce que vous voulez.

from u in Users 
let p = Photos.Where(p => p.Username == u.Username).FirstOrDefault() 
where p <> null 
select new 
{ 
    u.Username, 
    p.ID 
}; 

Cependant, il convient de noter que vous pouvez être mieux écrire main optimisée SQL et récupérer les objets à l'aide db.ExecuteQuery<User> ou similaire.

+0

Cette requête est vraiment mauvaise pour les performances? – Shar

+0

Non, pas vraiment. Cela devrait suffire. mais, il semble un peu perdu. –

2

Vous pouvez utiliser le regroupement:

from p in photos 
group p by p.username into g 
select new 
    { 
    Username = g.Key, 
    PicId = g.First().Id 
    }; 

Au lieu de première(), vous pouvez faire un autre filtrage ...

+0

Devrait-il aller avec mon code de jointure ou comme stand-alone? pouvez-vous écrire le code complet plz? – Shar

+0

Votre code de jointure était inutile, car vous saisissiez simplement le nom d'utilisateur de la table des utilisateurs, où la table d'images * l'avait déjà *. Profitez de situations comme celle-ci. – Will

+0

Je vois. mais cette requête ne me permet pas de sélectionner les utilisateurs de certian. Je veux d'abord sélectionner les utilisateurs en fonction de plusieurs paramètres (disons par exemple Username> 1000) et ensuite obtenir une photo pour chaque utilisateur. – Shar

1

Vous devriez mettre IsPrimary dans un état où. De plus, comme un utilisateur peut avoir zéro image, vous avez besoin d'une jointure à gauche.

EDIT: exmaple suit, (peut avoir faute de frappe)

from u in Users 
join p in (from p1 in Pictures where p1.IsPrimary select p1) on u.Username equals p.Username into pp 
from p in pp.DefaultIfEmpty() 
select new 
{ 
    u.UserName, 
    PicturePath = p == null ? "DummyPath" : p.PicturePath 
} 

EDIT: D'ailleurs, la réponse John Gietzen semble ne donne pas la réponse que vous demandez.

+0

Avez-vous une chance de me donner un exemple? plz. – Shar

0

 
var upic = from u in users 
      join p in pictures on u.UserName equals p.UserName into g 
      from o in g.DefaultIfEmpty() 
      where o == null || o.IsPrimary == true 
     select new { UserName = u.UserName, Id = (o == null ? "(No picture)" : o.Id) };