Ich arbeite an der gleichen Sache! Zuallererst: Mein Schema ist ein bisschen anders. Ich habe einen Benutzer, ein Thema und einen Kommentar. Das Thema ist nur eine Klasse mit einer Liste von Kommentar-IDs (IEnumerable long), mehr nicht. Der erste Kommentar ist der Beitrag.
Oh, wirklich vor allem kleine Warnung: Ich bin erst am Anfang mit Service Fabric, so könnte ich es falsch machen;)
Der Benutzer ist für mich nicht relevant. Ich speichere nur die Benutzer-ID auf dem Kommentar. Beim Abrufen einer Liste von Kommentaren bekomme ich die Benutzer vom statusbehafteten Benutzerdienst. Oder ich werde den Benutzernamen im Kommentar direkt speichern, noch nicht sicher.
Also das lässt mich mit Themen und Kommentare. Zuerst dachte ich, wir können einen Stateful TopicService und einen Stateful CommentService erstellen. Aber dann erkannte ich, dass ich für jedes Thema, das ich lade, den CommentService für jeden Kommentar aufrufen muss, um die Kommentare zu erhalten.
Also habe ich einen TopicService erstellt, der 2 IRelableDictionaries behandelt: Themen und Kommentare.
Immer wenn ein Kommentar gepostet wird, verwende ich die TopicId als Partitionsschlüssel und in dieser Partition wird der Kommentar gespeichert. Also nicht mit dem Kommentar !! Auf diese Weise befinden sich alle Kommentare für ein bestimmtes Thema in derselben Partition.
Wenn ich ein Thema mit allen Kommentaren lade, benutze ich die TopicId erneut als Partitionsschlüssel, hole das Thema aus dem reliabledictionary für die Themen und führe die Liste der Kommentar-IDs im reliabledictionary für die Kommentare durch. Nicht sicher, ob es hilft, aber mein GetComments sieht wie folgt aus:
var topics = await this.StateManager.GetOrAddAsync<IReliableDictionary<long, TopicModel>>("topics");
var comments = await this.StateManager.GetOrAddAsync<IReliableDictionary<long, CommentModel>>("comments");
List<CommentModel> result = new List<CommentModel>();
using (var tx = this.StateManager.CreateTransaction())
{
ConditionalValue<TopicModel> topic = await topics.TryGetValueAsync(tx, topicid);
if(topic.HasValue)
{
foreach(long commentid in topic.Value.CommentsInternal)
{
ConditionalValue<CommentModel> comment = await comments.TryGetValueAsync(tx, commentid);
if (comment.HasValue)
result.Add(comment.Value);
}
}
await tx.CommitAsync();
}
return result;
ich noch nicht fertig bin, das Verfahren einige weitere Arbeit.
Vielleicht hilft Ihnen :)
edit: OW gibt es ein Nachteil ist! Wenn Sie einen einzelnen Kommentar anhand seiner ID laden möchten, müssen Sie die topicid angeben. Also hat meine CommentModel-Klasse eine CommentId- und eine TopicId-Eigenschaft.
Danke für die Antwort. Ich dachte über Partitionierung nach, aber es schien mir ein bisschen "kompliziert", und ich suchte weiter nach einer einfacheren Lösung. Wie erhalten Sie alle Kommentare für einen bestimmten Benutzer? Warum nennen Sie 'CommitAsync', da keine Änderungen an zuverlässigen Sammlungen vorgenommen werden? Speichern Sie Kommentare in einer Liste in einem zuverlässigen Wörterbuch? Wenn ja, ist es nicht threadsicher und sollte vermieden werden. – cassandrad
Partitionierung ist nicht so schwierig. Es geht darum, Daten auf einem Knoten zu gruppieren. Service Fabric funktioniert dafür am besten. Es hängt auch davon ab, wie viele Kommentare sein werden. Wenn es in den Tausenden ist, stören Sie Partitionierung nicht. Wenn es in der Hunderttausende ... Partition! Alle Kommentare für einen bestimmten Benutzer können mit Azure Search oder einem separaten Index erstellt werden. Ich begehe als Habit. Ich habe eine Transaktion, also beende ich sie mit einem Commit. Kommentare in einer Liste Ja, ich benutze einen Actor (mit keiner Persistenz) um die Daten zu bearbeiten. Schauspieler verhalten sich single-threaded. Write = Actor, Lesen = Stateful Service. – Martin
Also, ein Schauspieler pro Thema zum Speichern von Kommentaren oder es ist im Dienst gespeichert und Sie bearbeiten nur Daten, Service-Methoden von einem Schauspieler aufrufen? Wie viele Benutzer können gleichzeitig neue Kommentare zu Themen hinzufügen/entfernen? – cassandrad