web-dev-qa-db-fra.com

Grouper par plusieurs colonnes dans LINQ en C #

J'ai une classe comme suit:

public class ActualClass
{
    public string BookName { get; set; }
    public string IssuerName { get; set; }
    public DateTime DateOfIssue { get; set; }
    public bool Status { get; set; }
}

Il contient les données suivantes dans le tableau: enter image description here

Je voudrais les regrouper par IssuerName et DateOfIssue pour la classe viewModel suivante:

public class ViewModel
{
   public string IssuerName { get; set; }
   public DateTime DateOfIssue { get; set; }
   public List<string> Books { get; set; }
}

Et les données seront affichées comme suit: ( Les données de capture d'écran seront remplacées par les données de la table précédente après un regroupement réussi) enter image description here

Attention particulière: Y a-t-il quelque chose qui ne va pas dans mon ViewModel selon mes attentes?

J'ai beaucoup essayé après avoir suivi certaines réponses de stackoverflow, mais aucune n'a fonctionné pour moi. Toute aide sera grandement appréciée.

Le code que j'ai essayé:

var viewmodel = from b in db.BookIssues
                group b by new
                {
                    b.IssuerName,
                    b.DateOfIssue
                }
                into g
                select new ViewModel()
                {
                    Name = g.key.IssuerName,
                    DateOfIssue = g.Key.DateOfIssue,
                    Books = g.ToList() //Actually this line of code is not working
                };
11
TanvirArjel

Books = g.ToList () // En fait, cette ligne de ne fonctionne pas

Probablement parce que la propriété Books est le type de List<string>, Pas List<ActualClass>.

Pouvez-vous essayer cette requête, j'ai ajouté b.Select(bn => bn.BookName).ToList() pour extraire uniquement les noms des livres:

var books = new List<ActualClass>
{
   new ActualClass { BookName = "A", DateOfIssue = new DateTime(2015, 10, 10, 10, 10, 0), IssuerName = "1" },
   new ActualClass { BookName = "B", DateOfIssue = new DateTime(2015, 10, 10, 10, 10, 0), IssuerName = "1" },
   new ActualClass { BookName = "C", DateOfIssue = new DateTime(2015, 10, 10, 10, 10, 0), IssuerName = "1" },
   new ActualClass { BookName = "D", DateOfIssue = new DateTime(2015, 10, 10, 10, 10, 0), IssuerName = "2" },
   new ActualClass { BookName = "E", DateOfIssue = new DateTime(2015, 10, 10, 12, 10, 0), IssuerName = "2" },
   new ActualClass { BookName = "F", DateOfIssue = new DateTime(2015, 10, 10, 12, 10, 0), IssuerName = "2" }
};

var result = books.GroupBy(x => new { x.IssuerName, x.DateOfIssue })
                .Select(b => new ViewModel
                {
                    Books = b.Select(bn => bn.BookName).ToList(),
                    // Accessing to DateOfIssue and IssuerName from Key.
                    DateOfIssue = b.Key.DateOfIssue,
                    IssuerName = b.Key.IssuerName
                });

J'ai groupé par: x.IssuerName, x.DateOfIssue. Je l'ai fait en passant un type anonyme dans GroupBy() de la manière suivante: x => new { x.IssuerName, x.DateOfIssue }.

Maintenant, ils sont dans la clé et vous pouvez accéder à IssuerName et DateOfIssue à partir de KEY dans l'instruction SELECT comme suit: b.Key.IssuerName Et b.Key.DateOfIssue.

13
kat1330

si vous devez sélectionner la liste des livres dans le résultat du groupe, vous avez besoin de Books = v.Select(c=>c.BookName).ToList() notez également que si vous avez l'heure de la date d'émission, vous devrez peut-être regrouper uniquement la partie date en utilisant EntityFunctions.TruncateTime une fonction. si vous ne stockez que la date, vous pouvez ignorer cette fonction.

var viewmodel  = db.BookIssues.GroupBy(x=>new {IssuerName =x.IssuerName, DateOfIssue=EntityFunctions.TruncateTime(x.DateOfIssue) })
.Select(v=>new ViewModel(){IssuerName =v.Key.IssuerName, DateOfIssue = v.Key.DateOfIssue, Books  = v.Select(c=>c.BookName).ToList() })
.ToList();
3
Damith