RavenDb получает сырой JSON без десериализации - PullRequest
0 голосов
/ 21 января 2019

Мне нужно восстановить JSON, хранящийся в базе данных RavenDb, зная его Id. Что здесь сложного, мне нужно получить его, прежде чем он будет десериализован в реальный объект. Причина в том, что мне нужно, чтобы он был в той же самой форме, в которой он был изначально сохранен, независимо от того, что происходит с классом CLR (он может радикально измениться или даже быть удален), потому что это аудит предыдущего состояния (он будет только отображается в этой точке, я не буду использовать его для чего-либо еще).

Если я пойду с

using (var session = Store.OpenSession())
{
    return JsonConvert.SerializeObject(session.Load<object>(id));
}

Я получаю JSON, отражающий текущее состояние базового типа, возможно, потому что он хранится в @metadata.Raven-Clr-Type. Поэтому я не вижу удаленных свойств и вижу пустые свойства, которых не было, когда они были впервые сохранены.

Я хотел использовать DocumentStore.DatabaseCommands.Get(), чтобы получить RavenJObject, но он уже удален в 4.1 в пользу Advanced.DocumentQuery, и я не смог найти способ сделать то, что я хочу, используя его.

Я также пытался использовать собственный AbstractIndexCreationTask, например:

class Object_AsJson : AbstractIndexCreationTask<JsonObject>
{
    public Configuration_AsJson()
    {
        Map = configuration => configuration.Select(x => AsJson(x).Select(y => y.Value));
    }
}

Но session.Load не принимает TIndexCreator, а в session.Query я не могу получить Id, потому что у меня нет свойств объекта, из которого можно сделать запрос.


Пример:

Если у меня есть этот класс:

public class Person
{
    string FullName { get; set; }
    int Age { get; set; }
}

И я сохраняю новый документ new Person { FullName = "John Samson", Age = 42 } под Id person/A-1, но через полгода я решаю изменить этот класс на:

public class Person
{
    string FirstName { get; set; }
    string LastName { get; set; }
    int Age { get; set; }
}

Теперь я хочу посмотреть, как выглядит JSON из person/A-1, но попытка загрузить его сопоставляет его с текущим состоянием Person, поэтому я получу:

{
  "FirstName": null,
  "LastName": null,
  "Age": 42
}

И я хочу получить

{
  "FullName": "John Samson",
  "Age": 42
}

Я вижу желаемый результат в графическом интерфейсе RavenDb Studio, но мне нужно получить его в своем коде для отображения в моем приложении.

Кто-нибудь знает, как с этим справиться? Был бы признателен только намек в правильном направлении.

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Хорошо, я наконец-то узнал, как это сделать, поэтому я оставлю это здесь любому, кто по какой-то причине хочет сделать то же самое.

По сути, вам просто нужно создать экземпляр GetDocumentsCommand и выполнить его. В моем случае это выглядит так:

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;
}
0 голосов
/ 21 января 2019

С https://github.com/ravendb/book/blob/v4.0/Ch03/Ch03.md#revisions-and-auditing

".... Аудит немного отличается. В то время как редакции сообщают вам, что изменилось, аудит сообщает вам, кем и как правило, для чего.RavenDB поддерживает этот вид аудита с использованием клиентских слушателей , которые могут предоставлять дополнительный контекст для документа при его изменении. .... "

Узнайте, как реализовать механизм аудитас обработчиками событий : 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

использовать что-то похожее на:

store.OnBeforeStore += (sender, args) =>
{
args.DocumentMetadata["Modified-By"] =
RequestContext.Principal.Identity.GetUserId();
};
...