9

Est-il possible de modéliser des relations entre des entités définies dans des NSManagedObjectModels distincts si les entités sont toujours utilisées dans un NSManagedObjectModel créé en fusionnant les modèles pertinents?Relations entre modèles dans NSManagedObjectModel à partir de modèles fusionnés?

Par exemple, supposons que le modèle 1 définit une entité Foo à la relation (one-to-one) toBar et que le modèle 2 définit une entité Bar avec une relation (one-to-one) toFoo. Je vais créer une pile CoreData en utilisant -[NSManagedObjectModel mergedModelFromModels], en fusionnant le modèle 1 et le modèle 2. Existe-t-il un moyen de définir ces relations dans le modeleur de données ou par programmation afin qu'elles se comportent comme si elles étaient des relations dans le modèle?

Répondre

16

Ni le modèle 1 ni le modèle 2 ne peuvent être chargés au moment de l'exécution sauf s'ils sont bien formés, c'est-à-dire, à moins que les relations toBar et toFoo aient des destinations. En outre, si le modèle 1 et le modèle 2 ont des modèles portant le même nom, vous ne pourrez pas créer un modèle fusionné à partir de ces modèles; ils ne seront pas coalisés, ils entreront en collision, ce qui est une erreur. Toutefois, vous pouvez utiliser manuellement l'API NSManagedObjectModel pour charger chaque modèle et créer manuellement un nouveau modèle contenant des entités des deux. Les classes NSEntityDescription et NSPropertyDescription (et ses sous-classes) implémentent le protocole NSCopying. Dans la plupart des cas, vous devriez pouvoir copier les propriétés de chaque modèle de composant vers votre modèle global. Par ailleurs, les classes NS*Description prennent toutes en charge un dictionnaire userInfo que vous pouvez modifier dans l'outil de modélisation de données de Xcode, que vous pouvez utiliser pour étiqueter la destination d'une relation en tant que remplaçant. Par exemple, dans le modèle 1, vous pouvez avoir une entité Bar avec une clé userInfoMyRealEntity et vérifier cela lors de la création de votre modèle fusionné, comme un signal pour utiliser l'entité réelle à la place.

Vous devrez également mettre des relations inverses en stand-in avec vos entités de remplacement; ceux-ci seront remplacés par de vrais inverses après la fusion. Cependant, vous n'avez pas à répliquer totalement vos entités de remplacement dans tous les modèles. Vous n'avez besoin que des relations inverses utilisées dans votre modèle réel dans une entité de peuplement.

Ainsi, si votre vrai Foo a un attribut name, et votre barre réel a un attribut kind, votre stand en Foo et Bar aura pas besoin de ceux-ci, tout en se toBar et toFoo relations.

est ici un code montrant ce dont je parle:

- (NSManagedObjectModel *)mergeModelsReplacingDuplicates:(NSArray *)models { 
    NSManagedObjectModel *mergedModel = [[[NSManagedObjectModel alloc] init] autorelease]; 

    // General strategy: For each model, copy its non-placeholder entities 
    // and add them to the merged model. Placeholder entities are identified 
    // by a MyRealEntity key in their userInfo (which names their real entity, 
    // though their mere existence is sufficient for the merging). 

    NSMutableArray *mergedModelEntities = [NSMutableArray arrayWithCapacity:0]; 

    for (NSManagedObjectModel *model in models) { 
     for (NSEntityDescription *entity in [model entities]) { 
      if ([[entity userInfo] objectForKey:@"MyRealEntity"] == nil) { 
       NSEntityDescription *newEntity = [entity copy]; 
       [mergedModelEntities addObject:newEntity]; 
       [newEntity release]; 
      } else { 
       // Ignore placeholder. 
      } 
     } 
    } 

    [mergedModel setEntities:mergedModelEntities]; 

    return mergedModel; 
} 

Cela fonctionne parce que la copie de NS*Description objets de base de données est par nom plutôt que par la valeur par rapport à l'entité de destination d'une relation et inverse (et aux subentities d'une entité aussi bien). Ainsi, même si un modèle est mutable, c'est-à-dire avant qu'il ne soit défini comme modèle pour un NSPersistentStoreCoordinator, vous pouvez utiliser des astuces comme celle-ci pour diviser votre modèle en plusieurs modèles.