it-swarm.com.de

Wie verwende ich LINQ, um ein Objekt auszuwählen?

Ich habe Daten, die so aussehen:

UserId   |  SongId
--------   --------
1          1
1          4
1          12
2          95

Ich habe auch folgende Klasse:

class SongsForUser
{
    public int User;
    public List<int> Songs;
}

Ich würde gerne LINQ verwenden, um aus meinen Daten eine Sammlung von SongsForUser-Objekten zu erstellen. Hier ist was ich bisher gefunden habe:

var userCombos = songs.UserSongs.Select(x => new SongsForUser() { User = x.UserId, 
                                                                  Songs = /*What goes here?*/ });

Wie würde ich meine Songs-Liste füllen?

Das Ergebnis sollte also zwei SongsForUser-Objekte sein. Für den Benutzer 1 hätte es 3 Elemente in der Liste Songs. Für den Benutzer 2 hätte es 1 Element in der Liste Songs.

24
Abe Miessler
songs.UserSongs.GroupBy(x => x.User).Select(g => new SongsForUser() 
{ 
    User = g.Key,
    Songs = g.Select(s => s.SongId).ToList()
});
37
ForEveR

Ich vermute, du willst:

var songsByUser = songs.UserSongs
                       .GroupBy(song => song.UserId, song => song.SongId)
                       .Select(g => new SongsForUser { User = g.Key,
                                                       Songs = g.ToList() });

Nach der GroupBy haben Sie eine Reihe von Gruppen, wobei der Schlüssel jeder Gruppe die Benutzer-ID ist und die Werte innerhalb der Gruppe die Song-IDs sind:

Key = 1, Values = 1, 4, 12
Key = 2, Value = 95

Dann konvertieren Sie das einfach in Ihren SongsForUser-Typ. Beachten Sie, dass Sie den () beim Aufruf des Konstruktors in einem Objektinitialisierer nicht explizit einschließen müssen. Dies ist implizit, es sei denn, Sie müssen Konstruktorargumente angeben.

Sie könnten tun dies alles in einem Aufruf GroupBy, übrigens:

var songsByUser = songs.UserSongs
         .GroupBy(song => song.UserId, song => song.SongId,
                  (user, ids) => new SongsForUser { User = user,
                                                    Songs = ids.ToList() });

Persönlich finde ich normalerweise, dass ein separater Select-Aufruf besser lesbar ist.

Sie können dies alles auch mit einem Abfrageausdruck machen:

var songsByUser = from song in songs.UserSongs
                  group song.SongId by song.UserId into g
                  select new SongsForUser { User = g.Key, Songs = g.ToList() };

EDIT: Das obige ist "anbieterneutral", klingt aber so, als würde es nicht mit LINQ to Entities funktionieren. Sie kann können es so machen, dass es so funktioniert:

var songsByUser = songs.UserSongs
                       .GroupBy(song => song.UserId, song => song.SongId)
                       .AsEnumerable()
                       .Select(g => new SongsForUser { User = g.Key,
                                                       Songs = g.ToList() });

Der Aufruf AsEnumerable zwingt die Gruppierung in der Datenbank, die endgültige Projektion (einschließlich des Aufrufs ToList) erfolgt jedoch lokal. Sie sollten die generierte SQL jedoch auf Effizienz überprüfen.

19
Jon Skeet

In seiner einfachsten Form können Sie einfach:

List<MapPoint> points = db.PropertyResearches.Where(a => a.deptId == 66).Select(x => new MapPoint { property = x.notes.Substring(0, 10), latitude = x.lat, longitude = [email protected] }).ToList();
0
pat capozzi

Nehmen wir an, Sie haben folgendes:

public class SongsForUser
{
    public int UserId;
    public List<int> Songs;
}

Dann wird eine Funktion wie diese hier funktionieren. Die Liste ist nur dazu da, __. Einige Daten zum Testen zu haben.

    public void Group()
    {
        List<Tuple<int, int>> SongRelations = new List<Tuple<int, int>>();

        SongRelations.Add(new Tuple<int, int>(1, 1));
        SongRelations.Add(new Tuple<int, int>(1, 4));
        SongRelations.Add(new Tuple<int, int>(1, 12));
        SongRelations.Add(new Tuple<int, int>(2, 95));

        var list = SongRelations.GroupBy(s => s.Item1)
                                .Select(r => new SongsForUser()
                                {
                                    UserId = r.Key,
                                    Songs = r.Select(t => t.Item2).ToList(),
                                });
    }

list enthält danach 2 Elemente vom Typ SongsForUser . Eines mit Benutzer 1 und einer Liste von Songs mit 1, 4 und 12 und eines mit Benutzer 2 und einer Liste von Songs mit 95.

0
Mare Infinitus