【问题标题】:RavenDB throws a JSON deserialisation error when retrieving documentRavenDB 在检索文档时抛出 JSON 反序列化错误
【发布时间】:2014-02-21 06:27:33
【问题描述】:

我刚刚完成了对我的应用程序的一轮重构,这导致我删除了一个不再需要的项目并将其类移到另一个项目中。这样做的一个副作用是我的 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

【问题讨论】:

    标签: c# ravendb


    【解决方案1】:

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

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

    【讨论】:

    • Cheers Shawn - 虽然我不需要获取实际文档的元数据,但很高兴看到我可以开始使用的脚本示例。我会看看我是否可以得到一些工作并发布我的发现。
    【解决方案2】:

    这里有两种可能的解决方案:

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

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

    【讨论】:

    • 这是一个生产系统,所以选项 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-28
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多