检索文档时,RavenDB会引发JSON反序列化错误

时间:2013-11-12 23:13:48

标签: c# ravendb

我刚刚完成了对我的应用程序的一轮重构,这导致我删除了一个不再需要的项目并将其类移动到另一个项目中。这样做的副作用是我的User类存储在RavenDB中,它具有移动到新程序集的类型的集合属性。一旦我尝试查询User类的会话,我就会收到Json反序列化错误。 here触及了这个问题,但答案并没有解决我的问题。这是令人讨厌的财产:

{
  "OAuthAccounts": {
    "$type": "System.Collections.ObjectModel.Collection`1[
      [Friendorsement.Contracts.Membership.IOAuthAccount, 
      Friendorsement.Contracts]], mscorlib",
    "$values": []
  },
}

OAuthAccountsUser的集合属性,用于在此处进行映射:

  

System.Collections.ObjectModel.Collection`1 [[Friendorsement.Contracts.Membership.IOAuthAccount,Friendorsement.Contracts]]

现在映射到这里:

  

System.Collections.ObjectModel.Collection`1 [[Friendorsement.Domain.Membership.IOAuthAccount,Friendorsement.Domain]]

Friendorsement.Contracts不再存在。它的所有类型现在都在Friendorsement.Domain

我尝试使用store.DatabaseCommands.StartsWith("User", "", 0, 128),但没有返回任何内容。

我已经尝试过UpdateByIndex,但没有达到目标:

store.DatabaseCommands.UpdateByIndex("Raven/DocumentsByEntityName",
    new IndexQuery {Query = "Tag:Users"},
        new[]
        {
            new PatchRequest { // unsure what to set here }
        });

我正在使用Raven 2.0

3 个答案:

答案 0 :(得分:2)

下面是一个简单的示例应用程序,它向您显示修补元数据。虽然你的例子有点不同,但这应该是一个很好的起点

namespace SO19941925
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            IDocumentStore store = new DocumentStore
                                   {
                                       Url = "http://localhost:8080",
                                       DefaultDatabase = "SO19941925"
                                   }.Initialize();

            using (IDocumentSession session = store.OpenSession())
            {
                for (int i = 0; i < 10; i++)
                {
                    session.Store(new User {Name = "User" + i});
                }
                session.SaveChanges();
            }

            using (IDocumentSession session = store.OpenSession())
            {
                List<User> users = session.Query<User>().Customize(x => x.WaitForNonStaleResultsAsOfNow()).ToList();
                Console.WriteLine("{0} SO19941925.Users", users.Count);
            }

            Operation s = store.DatabaseCommands.UpdateByIndex("Raven/DocumentsByEntityName",
                new IndexQuery {Query = "Tag:Users"},
                new ScriptedPatchRequest
                {
                    Script = @"this['@metadata']['Raven-Clr-Type'] = 'SO19941925.Models.User, SO19941925';"
                }, true
                );
            s.WaitForCompletion();
            using (IDocumentSession session = store.OpenSession())
            {
                List<Models.User> users =
                    session.Query<Models.User>().Customize(x => x.WaitForNonStaleResultsAsOfNow()).ToList();
                Console.WriteLine("{0} SO19941925.Models.Users", users.Count);
            }
            Console.ReadLine();
        }
    }

    internal class User
    {
        public string Name { get; set; }
    }
}

namespace SO19941925.Models
{
    internal class User
    {
        public string Name { get; set; }
    }
}

更新:根据上面的初步答案,这里是实际解决OP问题的代码:

store.DatabaseCommands.UpdateByIndex("Raven/DocumentsByEntityName",
    new IndexQuery {Query = "Tag:Users"},
    new ScriptedPatchRequest
    {
        Script = @"this['OAuthAccounts']['$type'] = 
            'System.Collections.ObjectModel.Collection`1[
            [Friendorsement.Domain.Membership.IFlexOAuthAccount, 
            Friendorsement.Domain]], mscorlib';",
        }, true
        );

答案 1 :(得分:0)

以下是两种可能的解决方案:

选项1:根据项目所处的状态,例如,如果您仍在开发中,您可以轻松地从Raven Studio中删除RavenDB中的该集合,并重新创建所有这些用户文档。然后,所有新的User文档都应具有正确的类名和程序集,然后应正确反序列化。显然,如果你已经投入生产,这可能不是一个好的选择。

选项2:根据您拥有的用户文档的数量,您应该能够手动编辑每个用户文档以指定正确的C#类名称和程序集,以便正确地反序列化它们。同样,如果你有太多的对象需要手动修改,这可能不是一个好的选择;但是,如果只有少数几个,那么打开每一个都不应该太糟糕,请转到元数据选项卡并粘贴“Raven-Entity-Name”和“Raven-Clr-Type”的正确值。

答案 2 :(得分:0)

我最终这样做了:

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);