RavenDB: sincronice documentos en la base de datos con datos de una fuente externa

¿Qué es más eficiente manera de sincronizar documentos en un RavenDB?

De una fuente externa obtengo un IEnumerable de BlogPosts con los que quiero hacer lo siguiente:

  • Agregar nuevos objetos que son nuevos para RavenDB
  • Actualizar objetos existentes
  • Eliminar objetos que se eliminaron en la fuente externa

El código que necesita implementación:

public void SyncIntoRaven(IEnumerable<BlogPost> postsToSync, IDocumentStore store) {
    // TODO: Implement
    // AddNewItems(postsToSync);

    // TODO: Implement
    // RemoveDeletedItems(postsToSync);

    // TODO: Implement
    // UpdateExistingItems(postsToSync);
}

Uno podría simplemente extraer todas las publicaciones de Blog de RavenDB y sincronizar localmente para luego hacer retroceder todos los cambios, pero quiero minimizar el tráfico a RavenDB. ¿Pero tal vez ese tampoco sea el enfoque correcto?

preguntado el 12 de junio de 12 a las 21:06

¿Sincronización entre Raven y qué? ¿Cómo realiza un seguimiento de las publicaciones de blog entre tiendas? ¿Tienen la misma identificación para ellas en ambas tiendas? -

@synhershko Misma identificación. Entre RavenDB y una fuente externa, como un archivo XML generado o lo que sea. -

2 Respuestas

Si está compartiendo la misma ID entre su fuente externa y RavenDB, puede hacerlo con bastante facilidad, de manera ACID y dentro de una transacción.

Realice un seguimiento de las ID que cambiaron entre las operaciones de sincronización, y una vez que tenga esa lista de ID, puede hacer esto fácilmente:

Abra una sesión, agregue los nuevos documentos usando session.Store(), cargue todos los documentos que necesitan actualizarse o eliminarse usando session.Load(string[]) session.Load().Lazily, realice las actualizaciones (y eliminaciones usando la opción Deferred ), y una vez que haya terminado, llame a session.SaveChanges().

Eso debería cubrirlo y suceder en solo un viaje de ida y vuelta al servidor.

De cualquier manera, nunca querrás hacer una sincronización completa cada vez. Siempre quieres usar deltas.

Respondido el 13 de junio de 12 a las 19:06

¿Funcionará esto con > 3500 identificaciones pasadas a session.Load(string[])? - seb nilsson

Y no puedo saber qué documentos son nuevos sin obtener todas las identificaciones de la tienda, ¿verdad? - seb nilsson

Esto debería funcionar para esa cantidad de identificaciones, sí, pero es posible que desee hacerlo en lotes más pequeños. Obtendrá nulos para identificaciones inexistentes, así es como sabría que aún no existen. O a través de su mecanismo de seguimiento. - sinhershko

Todavía recibo una solicitud de más, por tener que averiguar qué documentos están en Raven, pero no en los documentos externos, y es necesario eliminarlos. ¿Algún consejo sobre cómo solucionar esto? - seb nilsson

Ver en mi comentario a su respuesta - sinhershko

Con la ayuda en forma de descripción de sinhershko Lo descubrí y quería compartir el código, simplificado para mostrar los conceptos.

private void RefreshBlogPosts(IDocumentSession session, IList<BlogPost> parsedPosts) {
    var parsedPostsIds = parsedPosts.Select(x => x.Id);
    var storePosts = session.Load<BlogPost>(parsedPostsIds);

    // Update existing or create new posts
    for(int i = 0; i < storePosts.Count(); i++) {
        var parsedPost = parsedPosts[i];

        var storePost = storePosts[i];
        if(storePost == null) {
            storePost = parsedPost;

            session.Store(storePost);
        } else {
            // Update post's properties
        }
    }

    // Find posts IDs no longer in database
    var removedPostIds = session.Query<BlogPost>().Select(x => x.Id)
        .Where(postId => !parsedPostsIds.Contains(postId));

    foreach(var removedPostId in removedPostIds) {
        session.Advanced.Defer(new DeleteCommandData() { Key = removedPostId });
    }

    session.SaveChanges();
}    

contestado el 23 de mayo de 17 a las 13:05

No hay necesidad de session.Store si solo actualizó un objeto existente que obtuvo usando Load<>(). Simplemente actualice el objeto y SaveChanges() se encargará del resto. Magia UoW. - sinhershko

Además, la segunda consulta no funcionará, .Contains() lanzará NotImplementedException. El operador In es lo que generalmente usará, pero en este caso será más fácil rastrear las eliminaciones en su sistema y enviar esas ID como una lista separada. - sinhershko

No hay Contains ahí. Lo cambié, aunque solía ser sobre una colección local. - seb nilsson

No puedo realizar un seguimiento de las eliminaciones en el sistema, RavenDB es el lugar de seguimiento y requiere una sincronización anterior. ¿Tengo que seguir usando session.Store para los objetos nulos? - seb nilsson

Un nulo no se rastrea, un nulo no es nada, significa que la ID no se encontró en el servidor, por lo tanto, no hay nada que rastrear. - sinhershko

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.