模型命名空间更改后,RavenDB会抛出转换异常

时间:2012-06-27 10:33:44

标签: .net ravendb

在数据库中,我已经存储了数百个文档。现在系统架构已经改变,并且(其中)模型被迁移到不同的命名空间(在不同的程序集中)。

下面显示了示例文档的元数据:

enter image description here

和我用来获取此类文档的代码:

var configuration = documentSession.Load<One.Social.Core.Entities.Setting>("Setting");
抛出异常的

[InvalidCastException: Unable to cast object of type 'One.QA.Core.Entities.Setting' to type 'One.Social.Core.Entities.Setting'.]

更新:

类似的错误,但来自NewtonsoftJson,我在dosument里面有指定类型的集合,现在已经改变了。

在数据库中我有问题文档,其中包含答案列表:

enter image description here

在代码中,类型如下:

namespace One.Social.Ask.Web.Models
{
    public class Question
    {        
        public string Content { get; set; }
        public IList<One.Social.Ask.Web.Models.Answer> Answers { get; set; }        
    }
}

Answers命名空间已更改。此外,现在它来自IList&lt;&gt;,没有ICollection&lt;&gt;。我现在不需要$type meta,它应该是:

enter image description here

虽然它现在是一个列表,但由于旧的$type信息,错误会上升:

Newtonsoft.Json.JsonSerializationException: Error resolving type specified in JSON 'System.Collections.ObjectModel.Collection`1[[One.QA.Core.Entities.Answer, One.QA.Core]], mscorlib'. ---> Newtonsoft.Json.JsonSerializationException: Could not find type 'System.Collections.ObjectModel.Collection`1[[One.QA.Core.Entities.Answer, One.QA.Core]]' in assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

迁移所有文档以反映当前类型名称的最佳方法是什么?有内置机制吗?

顺便说一下:我正在使用RavenDB - Build#960

4 个答案:

答案 0 :(得分:3)

亚雷克, 问题的原因是你有这两种类型。 如果您删除QA类型,它将起作用。 或者,你可以像怀亚特所建议的那样强迫这一点。

答案 1 :(得分:3)

我遇到了同样的问题并最终做到了这一点:

Advanced.DatabaseCommands.UpdateByIndex(
    "Raven/DocumentsByEntityName",
        new IndexQuery {Query = "Tag:Album"},
        new []{ new PatchRequest() { 
            Type = PatchCommandType.Modify, 
            Name = "@metadata", 
            Nested= new []{ 
                new PatchRequest{
                    Name= "Raven-Clr-Type",
                    Type = PatchCommandType.Set,
                    Value = "Core.Model.Album, Core" }}}},
        false);

答案 2 :(得分:1)

您需要直接修补ravendb文档而不尝试反序列化它们。我自己从来没有这样做,但我认为使用IDocumentSession.Advanced.DatabaseCommands中的方法完成了魔术,特别是Patch method

我真的没有什么可以测试的,但我认为代码应该是这样的:

//s is your document session
var toUpdate = s.Advanced.DatabaseCommands.StartsWith("Setting", 0, 128);
foreach (var d in toUpdate)
{
    var p = new PatchRequest();
    p.AllPositions = true;
    p.Type = PatchCommandType.Modify;
    d.Metadata["Raven-Clr-Type"] = "MyNewType";
    p.Value = d.ToJson();
    s.Advanced.DatabaseCommands.Patch(d.Key, new []{p});
}
// push forward and repeat for all items in collection

还有一种方法可以在不循环收集的情况下执行此操作,但我不确定如何正确实现。

答案 3 :(得分:0)

重命名后,我遇到了casting exception完全相同的问题。 正如前面的答案所述,我最终根据this snippet修补了我的所有文件。

我们需要更新两个字段:Raven-Entity-NameRaven-Clr-Type

示例

MyType重命名为MyNewType,将名称空间从My.Namespace.MyType更新为My.New.Namespace.MyNewType

Raven-Entity-Name需要从MyTypes更改为MyNewTypes。复数为何? &#34;约定优于配置&#34;方法,as explained here

Raven-Clr-Type需要从My.Namespace.MyType更新为My.New.Namespace.MyNewType

<强>代码

public static void PatchMetadata()
        {
            var operation = session.Advanced.DocumentStore.DatabaseCommands
            .UpdateByIndex(
                // You can check your index name in the Studio Under INDEXES.
                    "Raven/DocumentsByEntityName",
                //  query that will be performed
                    new IndexQuery
                    {
                        // A collection in RavenDB is a set of documents with the same tag. 
                        // The tag is defined in Raven-Entity-Name.
                        Query = "Tag:MyTypes"
                    }, new[]
                                {
                                    new PatchRequest
                                        {
                                            Type = PatchCommandType.Modify,
                                            Name = "@metadata",
                                            Nested = new[]
                                                {
                                                    new PatchRequest
                                                        {
                                                            Type = PatchCommandType.Set,
                                                            Name = "Raven-Entity-Name",
                                                            Value = new RavenJValue("MyNewTypes")
                                                        }
                                                        ,
                                                    new PatchRequest
                                                        {
                                                            Type = PatchCommandType.Set,
                                                            Name = "Raven-Clr-Type",
                                                            Value = new RavenJValue("My.New.Namespace.MyNewType, RavenDbPatching")
                                                        }
                                                }
                                        }
                                },
                    new BulkOperationOptions() { AllowStale = true }
            );
        }