2012-06-27 13 views
11

En la base de datos, ya he almacenado cientos de documentos. Ahora la arquitectura del sistema ha cambiado y (entre otros) los modelos se migraron a diferentes espacios de nombre (en un ensamblaje diferente).RavenDB lanza la excepción de conversión después del cambio del espacio de nombres de los modelos

A continuación, se muestra metadatos del documento de muestra:

enter image description here

y el código que estoy usando para traer dicho documento:

var configuration = documentSession.Load<One.Social.Core.Entities.Setting>("Setting"); 

que arroja fundición excepción:

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

ACTUALIZACIÓN:

Error similar pero desde NewtonsoftJson se eleva, mientras que tengo una colección del tipo especificado dentro del dosument, que ahora ha cambiado.

En la base de datos que tienen documento de preguntas, que contiene una lista de respuestas:

enter image description here

En el código, el tipo que se parece a:

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

Respuestas espacio de nombres cambiados. Además, ahora se deriva de IList <>, no ICollection <>. No necesito la meta ahora $type, debe ser:

enter image description here.

Si bien es una lista ahora, un error se eleva debido a la edad $type información:

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'. 

¿Cuál es la mejor manera de migrar todos los documentos para reflejar los nombres de los tipos actuales? ¿Hay algún mecanismo incorporado?

Por cierto: estoy usando RavenDB - Build # 960

Respuesta

3

Jarek, El motivo del problema es que TIENE ambos tipos. Si elimina el tipo de control de calidad, simplemente funcionará. O bien, puede hacer lo que sugiere Wyatt y forzar esto.

+0

Gracias, de hecho tuve un segundo tipo. Después de eliminar, Raven ha cambiado automáticamente la meta información del documento al tipo actual "Raven-Clr-Type": "One.Social.Ask.Web.Models.Setting, One.Social. Ask.Web". ¿Puedes echarle un vistazo a la actualización de mi pregunta? Tengo otro problema similar. – jwaliszko

+0

Esto es correcto. Resolvió mi problema :) Gracias Ayende –

+0

Tuve el mismo problema que ni siquiera pude eliminar los documentos de RavenDB Studio. ¡Esto se debía a que el viejo clr-type todavía estaba presente en un plugin! Tuve que detener ravendb, eliminar el complemento, reiniciar Ravendb, eliminar todos los documentos en el estudio (funcionó ahora), detener de nuevo ravendb, volver a instalar el complemento y volver a iniciar ravendb. – ldx

1

Tendrá que parchear los documentos ravendb directamente sin intentar deserializar ellos. No he tenido que hacer esto nunca, pero creo que la magia se hace usando los métodos encontrados en IDocumentSession.Advanced.DatabaseCommands, particularmente el Patch method.

yo no tengo nada en contra de probar, pero creo que el código debería ser similar:

//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 

También hay una manera de hacer esto sin bucle a través de la colección, pero no estoy seguro cómo hacer eso correctamente

+1

hacerlo sin bucle a través de todos los documentos, puede utilizar las operaciones basadas en conjuntos, consulte http://ravendb.net/docs/client-api/set-based- operaciones –

+1

Gracias Matt, no estoy seguro de si funcionan si estás jugando con metadatos. –

+0

Gracias por el consejo. ¿Qué ocurre si tengo una colección de algún tipo dentro del documento y el espacio de nombres del tipo de colección cambia? (ver actualización) – jwaliszko

3

que tenían el mismo problema y terminó haciendo esto:

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

que enfrentan el mismo problema exacto de casting exception después de un cambio de nombre. Como se indicó en las respuestas anteriores, terminé parcheando todos mis documentos basados ​​en this snippet.

Tenemos que actualizar dos campos: Raven-Entity-Name y Raven-Clr-Type.

Ejemplo

Cambiar el nombre de MyType a MyNewType, la actualización del espacio de nombres My.Namespace.MyType-My.New.Namespace.MyNewType.

Raven-Entity-Name debe cambiarse de MyTypes a MyNewTypes. ¿Por qué plural? Enfoque "Convención sobre la configuración", as explained here.

Raven-Clr-Type necesita ser actualizado desde My.Namespace.MyType hasta .

Código

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 } 
      ); 
     } 
Cuestiones relacionadas