我在RavenDB中序列化/反序列化时遇到一些问题。我在存储数据时没有问题,但在查询文档时遇到了问题。
我有一个相当复杂的Account类,它是从实体框架v4.3 POCO生成器生成的:
[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(是的,与RavenDB Buid 960附带的.dll相同)来填充SerializedText字段,然后将其存储到RavenDB。这个过程会起作用的!我会从RavenDB中获取AccountWrapper对象,然后手动反序列化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:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonContract.cs:line 172
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IWrappedCollection wrappedList, JsonReader reader, String reference, JsonArrayContract contract) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 774
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.<>c__DisplayClass1.<CreateAndPopulateList>b__0(IList l, Boolean isTemporaryListReference) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 744
at Newtonsoft.Json.Utilities.CollectionUtils.CreateAndPopulateList(Type listType, Action`2 populateList) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonUtilitiesCollectionUtils.cs:line 233
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateList(JsonReader reader, String reference, JsonArrayContract contract) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 732
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String reference) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 495
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 238
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueProperty(JsonReader reader, JsonProperty property, JsonConverter propertyConverter, Object target, Boolean gottenCurrentValue, Object currentValue) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 213
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonReader reader, Object target) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 617
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, String id) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 1203
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, String id) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 956
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 433
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 236
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract, JsonConverter converter) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 221
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonSerializationJsonSerializerInternalReader.cs:line 117
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonJsonSerializer.cs:line 421
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) in d:DevelopmentReleasesJsonWorkingSrcNewtonsoft.JsonJsonSerializer.cs:line 413
at Raven.Client.Connection.JsonExtensions.Deserialize(RavenJObject self, Type type, DocumentConvention convention) in c:BuildsRavenDB-StableRaven.Client.LightweightConnectionJsonExtensions.cs:line 30
at Raven.Client.Document.InMemoryDocumentSessionOperations.ConvertToEntity[T](String id, RavenJObject documentFound, RavenJObject metadata) in c:BuildsRavenDB-StableRaven.Client.LightweightDocumentInMemoryDocumentSessionOperations.cs:line 416
at Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity[T](String key, RavenJObject document, RavenJObject metadata) in c:BuildsRavenDB-StableRaven.Client.LightweightDocumentInMemoryDocumentSessionOperations.cs:line 340
at Raven.Client.Document.SessionOperations.QueryOperation.Deserialize[T](RavenJObject result) in c:BuildsRavenDB-StableRaven.Client.LightweightDocumentSessionOperationsQueryOperation.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:BuildsRavenDB-StableRaven.Client.LightweightDocumentSessionOperationsQueryOperation.cs:line 114
at Raven.Client.Document.AbstractDocumentQuery`2.GetEnumerator() in c:BuildsRavenDB-StableRaven.Client.LightweightDocumentAbstractDocumentQuery.cs:line 616
at Raven.Client.Linq.RavenQueryInspector`1.GetEnumerator() in c:BuildsRavenDB-StableRaven.Client.LightweightLinqRavenQueryInspector.cs:line 98
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
这应该有效,你能提供更多的细节吗?如果测试用例失败,那就太好了。
无论如何,您可以使用以下选项进行自定义:
documentStore.Conventions.CustomizeSerializer