Laden...

[LINQ] Letzte Nachricht aus Nachrichten-Konversation herausfinden

Erstellt von Yheeky vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.923 Views
Y
Yheeky Themenstarter:in
200 Beiträge seit 2008
vor 12 Jahren
[LINQ] Letzte Nachricht aus Nachrichten-Konversation herausfinden

Hi,

ich habe eine MSSQL-Datenbank und eine Nachrichten-Tabelle.
Über meine Webseite können sich Benutzer Nachrichten versenden. Ich möchte die Anzeige in Konversationen anzeigen lassen.
Ich habe folgendes Tabellendesign (inkl. Testdaten):

BenutzerID_Sender, BenutzerId_Empfänger, Nachricht, Datum
2, 1, Hi, 05.06.2011 01:30
1, 2, Hi zurück, 05.06.2011 01:35
2, 1, Wie geht´s dir?, 05.06 01:38
3, 4, Hi there, 05.06.2011 1:33
4, 3, Hi, how are you?, 05.06.2011 01:40

Nun bin ich am Überlegen, wie ich eine LINQ Query zusammenbastele, die mir die beiden Konversationen mit der letzten Nachricht (und Datum) zurückgibt. Kann mir da vielleicht jemand auf die Sprünge helfen? Irgendwie bekomme ich das nicht so wirklich hin 😦

Danke schonmal und Gruß!
Yheeky

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo,

mit einer Query wirds ein bischer trickreich, aber mit zwei ist es nicht so schwer:


Konversation letzte = konversationen
	.OrderByDescending(k => k.Datum)
	.First();

IEnumerable<Konversation> konversationDerLetztenPartner = konversationen
	.Where(k => 
		k.EmpfängerID == letzte.EmpfängerID && k.SenderID == letzte.SenderID ||
		k.EmpfängerID == letzte.SenderID && k.SenderID == letzte.EmpfängerID);

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Y
Yheeky Themenstarter:in
200 Beiträge seit 2008
vor 12 Jahren

Hi,

danke erstmal für die schnelle Antwort zu später/früher Stunde 😉
Das war aber leider nicht das was ich gesucht habe. Ich habe es aber auch nicht genau ausgedrückt 😉
Gehe nicht von den Daten aus dem ersten Posting aus, sondern von diesen hier:

2, 1, Hi, 05.06.2011 01:30
1, 2, Hi zurück, 05.06.2011 01:35
2, 1, Wie geht´s dir?, 05.06 01:38
3, 1, Hi there, 05.06.2011 1:33
1, 3, Hi, how are you?, 05.06.2011 01:40

Nun stelle dir vor, ich wäre der Benutzer mit der ID 1. Ich gehe in den Posteingang und dort sollen nun ALLE meine Konversationen aufgelistet werden, nicht nur die letzte! Es soll auf der Hauptseite von jeder einzelnen Konversation die letzte Nachricht angezeigt werden, damit man weiss, was die letzte Nachricht in der Konversation war. Bei den obrigen Daten wäre das:

Konversation zwischen 1 und 2:
Wie geht´s dir?, 05.06 01:38

Konversation zwischen 1 und 3:
Hi, how are you?, 05.06.2011 01:40

Nun dürfte sich das Ganze noch etwas schwieriger gestalten, nehme ich an 😉
Ich habe es leider noch nicht hinbekommen...vielleicht hast du ja noch eine Idee.

Gruß Yheeky

D
615 Beiträge seit 2009
vor 12 Jahren

Hallo Yheeky

Es soll auf der Hauptseite von jeder einzelnen Konversation die letzte Nachricht angezeigt werden, damit man weiss, was die letzte Nachricht in der Konversation war. Bei den obrigen Daten wäre das:

-> Inhalt nach Datum sortieren
-> gfoidl's Linq Ausdruck verwenden
-> FirstOrDefault , oder Take(1) verwenden

Beste Grüsse

Diräkt

Y
Yheeky Themenstarter:in
200 Beiträge seit 2008
vor 12 Jahren

Das geht so nicht.

-> Inhalt nach Datum sortieren

Das hat er doch oben auch schon gemacht. Dann bekomme ich eine Liste, die so aussieht:

1, 3, Hi, how are you?, 05.06.2011 01:40
2, 1, Wie geht´s dir?, 05.06 01:38

1, 2, Hi zurück, 05.06.2011 01:35
3, 1, Hi there, 05.06.2011 01:33
2, 1, Hi, 05.06.2011 01:30

-> gfoidl's Linq Ausdruck verwenden

Damit bekomme ich die Konversation des letzten Partners, aber nicht alle letzten Konversationen. Ich möchte quasi die dick-markierten Einträge in dem Fall bekommen.
Jede Konversation hat ja logischerweise zwei beteiligte Benutzer. Wer von beiden zuletzt geschrieben hat, ist egal. Es soll im eigenen Profil angezeigt werden. Es müsste quasi ein DISTINCT gemacht werden, bei dem aber 1, 2 und 2, 1 als eins behandelt werden...weiss aber nicht, wie ich das umsetzen könnte.

Gerne könnte ihr mir auch in Form von T-SQL helfen, dann kann ich das vielleicht auch umsetzen.

Das Prinzip wird übrigens u.a. auch bei Facebook verwendet. Nur falls es noch etwas unklar ist, was ich genau will. Vielleicht konnte ich mich bisher noch nicht so gut ausdrücken 😃

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo,

gruppier (mit GroupBy) einfach nach den IDs und dann hast du schon mal die Konversationen zusammengefasst. Jede Gruppe kann dann sortiert nach Datum angezeigt werden und in der Übersicht halt das Letzte (oder das Erste - je nachdem wie sortiert wurde).

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Y
Yheeky Themenstarter:in
200 Beiträge seit 2008
vor 12 Jahren

Also ich habe es jetzt gelöst und zwar mit einem foreach.
Folgenden Workaround habe ich gemacht.

Ich habe mir erst die Benutzer geholt, mit denen der aktuelle Benutzer eine Konversation hatten:

var query = (from k in Konversationen
                         where (k.BenutzerId_Empfänger == benutzerId)
                         orderby k.Datum descending
                         select k.BenutzerId_Sender).Distinct();

Dann bin ich diese Benutzer per foreach durchgegangen, habe alle Nachrichten aus der DB geholt, die mit der Konversation zu tun haben.

foreach (var queryItem in query)
{
	var newestItem = (from k in Konversationen
					   where
						   (k.BenutzerId_Sender == queryItem  && k.BenutzerId_Empfänger == benutzerId) ||
						   (k.BenutzerId_Sender == benutzerId && k.BenutzerId_Empfänger == queryItem)
					   select k).OrderByDescending(d => d.Datum).First();

	returnListe.Add(newestItem);
}

Die returnListe enthält dann alle Daten, die ich gesucht habe 😃

EDIT:
Ich habe die foreach nun durch eine Lambda-Expression ersetzt:

return query.Select(queryItem => (from k in Konversationen
                                 where (k.BenutzerId_Sender == queryItem && k.BenutzerId_Empfänger == benutzerId) || (k.BenutzerId_Sender == benutzerId && k.BenutzerId_Empfänger == queryItem)
                                 select k).OrderByDescending(d => d.Datum).First()).ToList();

Danke für eure Hilfe!

Gruß Yheeky

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo,

schau dir mal Enumerable.GroupBy Method (System.Linq) an - damit geht es deklarativer.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"