Пользовательский сериализатор и десериализатор RavenDB

У меня возникли проблемы с сериализацией/десериализацией в RavenDB. У меня нет проблем с хранением данных, но есть проблема при запросе документов.

У меня есть довольно сложный класс Account, который был создан из генератора POCO Entity Framework v4.3:

[Serializable]
public class Account
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime CreatedDate { get; set; }
public List<Product> ProductsOwned { get; set; }
public bool IsActive { get; set; }
public Nullable<DateTime> DOB { get; set; }
public Address HomeAddress { get; set; }

// shortened for brevity
}

Когда я запрашиваю свои объекты и возвращаю их в виде списка, я получаю ошибку отражения .NET «объект не соответствует целевому типу».

var results = (from account in mySession.Query<Account>()
               where account.IsActive == true
               select account).ToList<Account>(); // this is where error occurs

Я думал, что это может быть из-за того, что у меня есть другие вложенные классы и значения NULL, которые также сериализуются при сохранении, но я обнаружил, что могу создать класс «обертки» с именем AccountWrapper следующим образом:

public class AccountWrapper
{
     public Guid Id { get; set; }
     public string SerializedText { get; set; }

}

Здесь я бы вручную использовал JSON.NET (да, ту же .dll, которая поставляется с RavenDB Buid 960), чтобы заполнить поле SerializedText, а затем сохранить его в RavenDB. Этот процесс будет работать! Я бы получил объект AccountWrapper из RavenDB, а затем вручную десериализовал содержимое SerializedText. Это наводит меня на мысль, что может быть проблема с процессом (де) сериализации по умолчанию.

Итак, мой вопрос: есть ли способ вручную переопределить функции сериализации/десериализации в RavenDB, когда я сохраняю/загружаю свои документы? Если да, может ли кто-нибудь показать мне чистый пример того, как это сделать? Затем я мог бы заставить его использовать стандартный JsonConverter.Serialize() как часть JSON.NET.

Очевидно, что использование AccountWrapper — плохая идея, потому что я не могу индексировать «реальные» данные, которые мне нужно запрашивать.

(Полная трассировка стека исключения ниже)

     System.Reflection.TargetException: Object does not match target type.  at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
   at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Newtonsoft.Json.Serialization.JsonContract.InvokeOnDeserialized(Object o, StreamingContext context) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonContract.cs:line 172
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IWrappedCollection wrappedList, JsonReader reader, String reference, JsonArrayContract contract) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 774
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.<>c__DisplayClass1.<CreateAndPopulateList>b__0(IList l, Boolean isTemporaryListReference) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 744
   at Newtonsoft.Json.Utilities.CollectionUtils.CreateAndPopulateList(Type listType, Action`2 populateList) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Utilities\CollectionUtils.cs:line 233
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateList(JsonReader reader, String reference, JsonArrayContract contract) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 732
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String reference) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 495
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 238
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueProperty(JsonReader reader, JsonProperty property, JsonConverter propertyConverter, Object target, Boolean gottenCurrentValue, Object currentValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 213
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonReader reader, Object target) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 617
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 1203
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 956
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 433
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 236
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract, JsonConverter converter) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 221
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 117
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonSerializer.cs:line 421
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonSerializer.cs:line 413
   at Raven.Client.Connection.JsonExtensions.Deserialize(RavenJObject self, Type type, DocumentConvention convention) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Connection\JsonExtensions.cs:line 30
   at Raven.Client.Document.InMemoryDocumentSessionOperations.ConvertToEntity[T](String id, RavenJObject documentFound, RavenJObject metadata) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:line 416
   at Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity[T](String key, RavenJObject document, RavenJObject metadata) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:line 340
   at Raven.Client.Document.SessionOperations.QueryOperation.Deserialize[T](RavenJObject result) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\SessionOperations\QueryOperation.cs:line 130
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Raven.Client.Document.SessionOperations.QueryOperation.Complete[T]() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\SessionOperations\QueryOperation.cs:line 114
   at Raven.Client.Document.AbstractDocumentQuery`2.GetEnumerator() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\AbstractDocumentQuery.cs:line 616
   at Raven.Client.Linq.RavenQueryInspector`1.GetEnumerator() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryInspector.cs:line 98
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

person Tim P.    schedule 19.08.2012    source источник
comment
Не могли бы вы показать трассировку стека исключения?   -  person asgerhallas    schedule 19.08.2012
comment
добавлена ​​трассировка стека исключения.   -  person Tim P.    schedule 19.08.2012


Ответы (1)


Это должно работать, можете ли вы предоставить дополнительную информацию, и неудачный тестовый пример был бы замечательным.

В любом случае, вы можете настроить это, используя:

documentStore.Conventions.CustomizeSerializer
person Ayende Rahien    schedule 22.08.2012