tipos tecnicas software sistemas sena riesgos pruebas proceso plan migracion introduccion interna inmigracion informaticos ilegal herramientas emigracion datos consecuencias computacionales causas aplicaciones iphone objective-c ios core-data core-data-migration

iphone - tecnicas - ¿Ejemplo o explicación de migración de datos centrales con múltiples pases?



tipos de migracion (3)

Estas preguntas están relacionadas:

Problemas de memoria al migrar grandes almacenes de datos CoreData en iPhone

Migración de datos de núcleo múltiple en fragmentos con iOS

Para citar el primer enlace:

Esto se discute en la documentación oficial en la sección "Pases múltiples", sin embargo, parece que su enfoque sugerido es dividir su migración por tipo de entidad, es decir, crear múltiples modelos de asignación, cada uno de los cuales migra un subconjunto de los tipos de entidades desde el completar el modelo de datos.

La aplicación de mi iPhone necesita migrar su almacén de datos central, y algunas de las bases de datos son bastante grandes. La documentación de Apple sugiere usar "múltiples pases" para migrar datos para reducir el uso de memoria. Sin embargo, la documentación es muy limitada y no explica muy bien cómo hacerlo. ¿Puede alguien indicarme un buen ejemplo o explicar en detalle el proceso de cómo lograrlo?


He descubierto lo que Apple insinúa en su documentation . En realidad es muy fácil, pero es un largo camino por recorrer antes de que sea obvio. Ilustraré la explicación con un ejemplo. La situación inicial es esta:

Modelo de datos Versión 1

Es el modelo que obtienes cuando creas un proyecto con la plantilla "aplicación basada en navegación con almacenamiento de datos básicos". Lo compilé e hice algunos golpes duros con ayuda de un bucle for para crear alrededor de 2k entradas, todas con valores diferentes. Ahi vamos 2.000 eventos con un valor de NSDate.

Ahora agregamos una segunda versión del modelo de datos, que se ve así:

Modelo de datos Versión 2

La diferencia es: la entidad Evento se ha ido, y tenemos dos nuevas. Uno que almacena una marca de tiempo como un double y el segundo que debe almacenar una fecha como NSString .

El objetivo es transferir todos los eventos de la Versión 1 a las dos nuevas entidades y convertir los valores a lo largo de la migración. Esto resulta en el doble de los valores cada uno como un tipo diferente en una entidad separada.

Para migrar, elegimos la migración a mano y esto lo hacemos con los modelos de mapeo. Esta es también la primera parte de la respuesta a su pregunta. Realizaremos la migración en dos pasos, ya que nos llevará mucho tiempo migrar 2k entradas y nos gusta mantener la huella de memoria baja.

Incluso podría continuar y dividir estos modelos de mapeo para migrar solo los rangos de las entidades. Digamos que tenemos un millón de registros, esto puede bloquear todo el proceso. Es posible reducir las entidades captadas con un predicado de filtro .

De vuelta a nuestros dos modelos de mapeo.

Creamos el primer modelo de mapeo así:

1. Nuevo archivo -> Recurso -> Modelo de mapeo

2. Elige un nombre, elegí StepOne

3. Establecer el modelo de datos de origen y destino

Mapeo del primer paso del modelo

La migración de pasos múltiples no necesita políticas de migración de entidades personalizadas, sin embargo, lo haremos para obtener un poco más de detalle para este ejemplo. Entonces agregamos una política personalizada a la entidad. Esta es siempre una subclase de NSEntityMigrationPolicy .

Esta clase de política implementa algunos métodos para que nuestra migración suceda. Sin embargo, es simple en este caso, así que tendremos que implementar solo un método: createDestinationInstancesForSourceInstance:entityMapping:manager:error:

La implementación se verá así:

StepOneEntityMigrationPolicy.m

#import "StepOneEntityMigrationPolicy.h" @implementation StepOneEntityMigrationPolicy - (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error { // Create a new object for the model context NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] inManagedObjectContext:[manager destinationContext]]; // do our transfer of nsdate to nsstring NSDate *date = [sInstance valueForKey:@"timeStamp"]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setTimeStyle:NSDateFormatterMediumStyle]; [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; // set the value for our new object [newObject setValue:[dateFormatter stringFromDate:date] forKey:@"printedDate"]; [dateFormatter release]; // do the coupling of old and new [manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping]; return YES; }

Paso final: la migración misma

Voy a saltear la parte para configurar el segundo modelo de mapeo que es casi idéntico, solo un timeIntervalSince1970 usado para convertir el NSDate a un doble.

Finalmente, necesitamos activar la migración. Voy a omitir el código repetitivo por ahora. Si lo necesitas, publicaré aquí. Se puede encontrar en documentation , es solo una fusión de los primeros dos ejemplos de código. La tercera y última parte se modificarán de la siguiente manera: en lugar de utilizar el método de clase de la clase mappingModelFromBundles:forSourceModel:destinationModel: utilizaremos initWithContentsOfURL: porque el método de clase devolverá solo uno, tal vez el primer modelo de mapeo encontrado en el haz.

Ahora tenemos los dos modelos de mapeo que se pueden usar en cada pasada del lopp y enviamos el método de migración al administrador de migración. Eso es.

NSArray *mappingModelNames = [NSArray arrayWithObjects:@"StepOne", @"StepTwo", nil]; NSDictionary *sourceStoreOptions = nil; NSURL *destinationStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMigrationNew.sqlite"]; NSString *destinationStoreType = NSSQLiteStoreType; NSDictionary *destinationStoreOptions = nil; for (NSString *mappingModelName in mappingModelNames) { NSURL *fileURL = [[NSBundle mainBundle] URLForResource:mappingModelName withExtension:@"cdm"]; NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL]; BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL type:sourceStoreType options:sourceStoreOptions withMappingModel:mappingModel toDestinationURL:destinationStoreURL destinationType:destinationStoreType destinationOptions:destinationStoreOptions error:&error2]; [mappingModel release]; }

Notas

  • Un modelo de mapeo termina en cdm en el paquete.

  • La tienda de destino debe proporcionarse y no debe ser la tienda de origen. Después de una migración exitosa puede eliminar el antiguo y cambiarle el nombre al nuevo.

  • Hice algunos cambios en el modelo de datos después de la creación de los modelos de mapeo, esto dio como resultado algunos errores de compatibilidad, que solo pude resolver al recrear los modelos de mapeo.


Supongamos que su esquema de base de datos tiene 5 entidades, por ejemplo, persona, estudiante, curso, clase y registro para usar el tipo estándar de ejemplo, donde la subclases de estudiantes, la clase implementa el curso y el registro se une a la clase y al alumno. Si ha realizado cambios en todas estas definiciones de tabla, debe comenzar en las clases base y seguir subiendo. Por lo tanto, no puede comenzar con la conversión de registros, ya que cada registro de registro depende de tener clases y estudiantes allí. Por lo tanto, comenzaría con la migración solo de la tabla Person, copiando las filas existentes en la nueva tabla y completando los nuevos campos existentes (si es posible) y descartando las columnas eliminadas. Realice cada migración dentro de un grupo de autorrelease, de modo que una vez que lo haga, su memoria vuelva a comenzar.

Una vez que haya terminado la tabla Person, puede convertir la tabla de estudiantes. Luego salte a Course y luego a Class, y finalmente a la tabla de registro.

La otra consideración es el número de registros, si al igual que Persona tuviera mil filas, tendría que, cada 100 o así, ejecutar el equivalente de una publicación de NSManagedObject, que es indicarle al contexto del objeto gestionado [moc refreshObject: ob mergeChanges: NO]; Establezca también su temporizador de datos obsoletos muy bajo, para que la memoria se descargue a menudo.