Ich entwerfe ein Protokollierungssystem, das seine Protokolleinträge in RavenDB speichert, und für dieses spezielle System möchte ich Dokumente speichern und später abfragen, die unterschiedliche Datenstrukturen haben, die auf dem Typ des protokollierten Ereignisses basieren. Betrachten Sie die folgenden Ereignisse, die ich protokollieren möchte:
Ich habe ein paar verschiedene Möglichkeiten, wie ich hier hingehen kann ...
Dieser Ansatz führt zu zwei verschiedenen Sammlungen in RavenDB, die leicht abgefragt werden können. Das Abrufen einer Vereinigung aller Protokolleinträge erfordert jedoch mehrere Abfragen und mehrere Roundtrips zum Server - einen für die LoginEvents und einen zweiten für die FileDeleteEvents. Mit nur zwei Ereignistypen macht das keinen großen Unterschied, aber das Problem wird mit der Anzahl der Ereignistypen erheblich schlimmer.
Ich habe diesen Ansatz versucht, aber RavenDB scheint Dokumente nach ihren tatsächlichen Typen zu speichern und abzufragen, nicht nach ihren Gattentypen - wenn ich Query<Event>().ToArray()
gemacht habe, habe ich null Ergebnisse erhalten. Um die Dokumente zurück zu bekommen, müsste ich nach ihren individuellen Typen fragen, was dies effektiv der obigen Option A entspricht.
Bei diesem Ansatz speichern wir immer einen Eintrag vom Typ Event, aber wir füllen seine Info-Eigenschaft mit der entsprechenden Info-Klasse, die Details zum Ereignistyp enthält. Zunächst schien diese Option die beste zu sein, da sie alle Protokolleinträge in einer einzigen Ereignissammlung speichert und die Abfrage der gesamten Sammlung erleichtert. Nehmen wir an, ich möchte nur die FileDelete-Ereignisse, bei denen der Dateiname "test.txt" ist. Dies wird ein wenig schwierig.
Im Folgenden wird beispielsweise ein etwas unklarer Fehler bezüglich des nicht indizierten Felds "Dateiname" angezeigt:
%Vor%Das folgende gibt, abgesehen davon, dass es nicht das ist, was ich will, null Ergebnisse zurück:
%Vor%Tatsächlich liefert die folgende Projektion, eine gemäß der Dokumentation unterstützte Operation, nicht einmal den erwarteten Typ, sondern nur eine Reihe seltsamer Zwischenergebnisse, die keinen Sinn ergeben:
%Vor%Obwohl diese Option aus Datenspeicherperspektive wahrscheinlich gut ist, schlägt sie aus der Perspektive der Abfragefähigkeit fehl. (Angenommen, ich baue die richtige Abfrage - es könnte einen anderen Weg geben, den ich nicht in Betracht ziehe).
Dieser Ansatz ist zwar aus Speicherperspektive ein wenig verschwenderisch, aus der Frage der Abfragefreundlichkeit jedoch trivial. Das Problem tritt auf, wenn Sie weitere Arten von Ereignissen hinzufügen, die Sie protokollieren möchten - dann beginnt die Anzahl der Eigenschaften zu steigen.
Ich kann das ziemlich trivial machen und effizient nach EFs Tabelle-pro-Vererbungsmuster suchen. Die Kehrseite dieses Ansatzes ist, dass Sql für dieses Problem ein ernsthafter Overkill ist - wir brauchen keine Datenkonsistenz und keine andere Strenge, die relationale Systeme bieten. Und meiner Erfahrung nach sind Sql-Inserts viel langsamer als die Dokumentenspeicherung in RavenDB (eine wichtige Überlegung für ein Protokollierungssystem).
Also, da sind die Optionen ... was denkst du? Gibt es etwas, was ich vermisst habe?
Möglicherweise verwandt: Sammlungsname in RavenDB angeben
Geh mit der Basisklasse-Sache. Der Trick besteht darin, Polymorphie zu verwenden und allen konkreten Typen den gleichen Typ-Tag-Namen zu geben. Jetzt können Sie sie leicht abfragen, da sie sich in derselben Sammlung befinden.
%Vor%Tags und Links entity-framework ravendb logging relational-database nosql