I need to recover JSON stored in RavenDb database knowing its Id
. What's tricky here, I need to get it before it is deserialized into an actual object. Reason for that is, I need it in exact same form it was first stored in, regardless what happens to the CLR class (it can drastically change or even be removed), because it is an audit of previous state (it's only going to be displayed at this point, I won't use it for anything else).
If I go with
using (var session = Store.OpenSession())
{
return JsonConvert.SerializeObject(session.Load<object>(id));
}
I get JSON reflecting current state of underlying type, probably because it's stored in @metadata.Raven-Clr-Type
. So I don't see removed properties, and I do see empty properties that didn't exist when it was first stored.
I wanted to use DocumentStore.DatabaseCommands.Get()
to get RavenJObject
, but it is already removed in 4.1 in favor of Advanced.DocumentQuery
and I couldn't find a way to do what I want using it.
I've also tried using own AbstractIndexCreationTask
like this:
class Object_AsJson : AbstractIndexCreationTask<JsonObject>
{
public Configuration_AsJson()
{
Map = configuration => configuration.Select(x => AsJson(x).Select(y => y.Value));
}
}
But session.Load
doesn't accept TIndexCreator
, and in session.Query
I can't get Id
because I don't have any properties of an object to make query from.
Example:
If I have this class:
public class Person
{
string FullName { get; set; }
int Age { get; set; }
}
And I store a new document new Person { FullName = "John Samson", Age = 42 }
, under Id
person/A-1
, yet half year later I decide to modify this class to:
public class Person
{
string FirstName { get; set; }
string LastName { get; set; }
int Age { get; set; }
}
Now I want to see how JSON of person/A-1
looks like, but an attempt to load it maps it to current state of Person
, so I will get:
{
"FirstName": null,
"LastName": null,
"Age": 42
}
And I want to get
{
"FullName": "John Samson",
"Age": 42
}
I can see my desired result in RavenDb Studio GUI, but I need to get it in my code to display it in my application.
Does anyone have any idea how to handle that? Just a hint in right direction would be appreciated.
From https://github.com/ravendb/book/blob/v4.0/Ch03/Ch03.md#revisions-and-auditing
"....
Auditing is a bit different. While revisions tell you what changed, auditing tells you by
whom and typically what for. RavenDB supports this kind of auditing using client-side listeners,
which can provide additional context for the document whenever it’s changed.
...."
See how to implement auditing mechanism with Event Handlers: https://github.com/ravendb/book/blob/v4.0/Ch04/Ch04.md#event-handlers
https://ravendb.net/docs/article-page/4.1/Csharp/migration/client-api/document-store#listeners
use something similar to:
store.OnBeforeStore += (sender, args) =>
{
args.DocumentMetadata["Modified-By"] =
RequestContext.Principal.Identity.GetUserId();
};
Okay, so I've finally found out how to do it, so I'll leave it here for anyone who, for some reason, wants to do the same.
Basically you just have to make an instance of GetDocumentsCommand
and execute it. In my case it looks like this:
using (var session = Store.OpenSession(database))
{
var command = new GetDocumentsCommand(id, null, false);
session.Advanced.RequestExecutor.Execute(command, session.Advanced.Context);
var result = command.Result.Results.FirstOrDefault();
var json = result?.ToString(); // At this point you already have your JSON
var jObject = JObject.Parse(json);
jObject.Remove("@metadata"); // If you don't want metadata in your JSON
jObject.Add("Id", id); // Because Id does not appear to be part of JSON
return jObject;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With