2017-06-13 3 views
1

J'ai cette classe dans mon code premier contexte cadre d'entité comme suit-LINQ compte dans une même table

class User 
{ 
    int UserId; 
    string Name;; 
    int ParentId; 
} 

table de base de données:

UserId Name ParentId 
    1   abc  0 
    3   pqr  1 
    4   xyz  1 

je voudrais sélectionner à partir des données ci-dessus comme en -

UserId  Name ChildQuantity 
    1   abc  2 
    3   pqr  0 
    4   xyz  0 

Puis-je le faire en utilisant LINQ ou Lambda?

Répondre

2

Vous pouvez vous joindre à table pour lui-même (vous avez besoin d'un groupe rejoindre ici):

from u in db.Users 
join c in db.Users on u.UserId equals c.ParentId into children 
select new 
{ 
    u.UserId, 
    u.Name, 
    ChildQuantity = children.Count() 
}; 

Ou vous pouvez configurer une propriété de navigation pour la collecte des enfants dans la classe utilisateur. Avec cette propriété de navigation, la requête ressemblera à:

from u in db.Users 
    select new { 
     u.UserId, 
     u.Name, 
     ChildQuantity = u.Children.Count() 
    }; 

Je crois que c'est un peu plus propre. Tout ce que vous devez faire - ajouter une propriété d'association pour les enfants:

public class User 
{ 
    public int UserId { get; set; } 
    public string Name { get; set; }   
    public int? ParentId { get; set; } // Note: this property is not required 
    public IList<User> Children { get; set; } 
} 

et de fournir la cartographie:

modelBuilder.Entity<User>().HasMany(u => u.Children) 
    .WithOptional().HasForeignKey(u => u.ParentId).WillCascadeOnDelete(false); 

Et requête générée ressemblera:

SELECT 
    [Extent1].[UserId] AS [UserId], 
    [Extent1].[Name] AS [Name], 
    (SELECT 
     COUNT(1) AS [A1] 
     FROM [dbo].[Users] AS [Extent2] 
     WHERE [Extent1].[UserId] = [Extent2].[ParentId]) AS [C1] 
    FROM [dbo].[Users] AS [Extent1] 
+0

@Servey, j'ai essayé l'approche de la propriété de navigation. Mais il donne une exception - "System.Data.Entity.ModelConfiguration.ModelValidationException" s'est produite dans EntityFramework.dll ". De l'aide? –

+0

@ L'option s.k.paul avec 'join' fonctionne sans problème? –

+0

joindre fonctionne bien. J'ai juste essayé l'autre option "propriété d'association" que vous avez suggérée. Voici les détails de l'erreur - " UserDetail_Children_Source_UserDetail_Children_Target:: Les types de toutes les propriétés dans le rôle dépendant d'une contrainte référentielle doivent être les mêmes que les types de propriété correspondants dans le rôle principal Le type de propriété 'ParentId' sur l'entité ' UserDetail 'ne correspond pas au type de propriété' UserId 'sur l'entité' UserDetail 'dans la contrainte référentielle' UserDetail_Children '. " –

2

Quelque chose comme ça?

var ans = from p in src select new { p.UserID, p.Name, ChildQuantity = src.Where(c => c.ParentId == p.UserID).Count() }; 
+0

Ça sonne bien. Cela fonctionnera-t-il réellement? Laisse moi vérifier. Quoi qu'il en soit, merci pour l'idée. –

+0

son fonctionnement. Mais la réponse de Sergey Berezovskiy est plus descriptive. –