【问题标题】:Loading Core Data relationships from existing database ID relationships从现有的数据库 ID 关系加载 Core Data 关系
【发布时间】:2014-01-30 23:27:15
【问题描述】:

我有一个应用程序,它在表格中包含大量数据,我正在编写一个获取一小部分数据的移动应用程序。表中的数据使用 ID 来表示关系,我正在尝试将其加载到 Core Data 模型中并保留关系。

但似乎没有一种简单的方法可以告诉 Core Data,“对于这个关系,我想要另一个表的外键。”相反,我有这个怪物(这是六个异步 RestKit 查询中的一个的简化版本,这些查询将返回填充数据库):

[manager postObject:nil path:@"api/shiftservice/get" parameters:@{@"workerIds": @[@1]} success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    NSLog(@"Loaded shifts: %d", [[mappingResult array] count]);
    NSManagedObjectContext *context = [AppDelegate managedObjectContext];

    NSSet *positions = [context fetchObjectsForEntityName:@"NWPosition"];
    NSDictionary *positionDict = [NSMutableDictionary new];
    for (NWPosition *position in positions) [positionDict setValue:position forKey:position.positionId.stringValue];

    NSSet *workers = [context fetchObjectsForEntityName:@"NWWorker"];
    NSDictionary *workerDict = [NSMutableDictionary new];
    for (NWWorker *worker in workers) [workerDict setValue:worker forKey:worker.workerId.stringValue];

    NSSet *shifts = [context fetchObjectsForEntityName:@"NWShift"];
    for (NWShift *shift in shifts)
    {
        NWPosition *position = [positionDict valueForKey:shift.positionId.stringValue];
        position.shifts = [context fetchObjectsForEntityName:@"NWShift" withPredicateFormat:@"positionId = %d", position.positionId];
        shift.position = position;

        NSSet *tradesAsGetShift = [context fetchObjectsForEntityName:@"NWTrade" withPredicateFormat:@"getShiftId = %@", shift.shiftId];
        for (NWTrade *trade in tradesAsGetShift) trade.getShift = shift;
        shift.tradesAsGetShift = tradesAsGetShift;

        NSSet *tradesAsGiveShift = [context fetchObjectsForEntityName:@"NWTrade" withPredicateFormat:@"giveShiftId = %@", shift.shiftId];
        for (NWTrade *trade in tradesAsGiveShift) trade.giveShift = shift;
        shift.tradesAsGiveShift = tradesAsGiveShift;

        NWWorker *worker = [workerDict valueForKey:shift.workerId.stringValue];
        worker.shifts = [context fetchObjectsForEntityName:@"NWShift" withPredicateFormat:@"workerId = %d", worker.workerId];
        shift.worker = worker;
    }
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    NSLog(@"Failed to load shifts with error: %@", [error localizedDescription]);
}];

我在 http://www.cocoawithlove.com/2008/03/core-data-one-line-fetch.html 使用 Matt Gallagher 的 One-Line Fetch 的修改版本作为 fetchObjectsForEntityName

无论如何,这对我来说似乎很可怕,就像我错过了一些明显的东西。有没有办法告诉 Core Data 数据库风格的外键?如果没有,是否有一种简单的方法来填充它们?因为为每一个实体做这么多的获取肯定看起来不是正确的方法。如果 RestKit 在这方面有所帮助,那就更好了。

【问题讨论】:

  • RestKit 应该处理外键(Core Data 没有)。显示您收到的 JSON 和您拥有的映射。您是否在映射中添加了外键关系?

标签: core-data restkit


【解决方案1】:

不,但应该不需要设置反向关系。

【讨论】:

    【解决方案2】:

    感谢 Wain 和他富有洞察力的评论,我设法让 RestKit 以一种相当优雅的方式为我做这件事。这是我设置外键关系的方法。我设置了每个关系的两端,以便任何一组数据都可以先进入,并且关系仍然可以正确填充。

    首先,我设置了管理器,告诉它使用 JSON 序列化:

    RKManagedObjectStore *store = [AppDelegate managedObjectStore];
    
    RKObjectManager *manager = [[RKObjectManager alloc] initWithHTTPClient:oauthClient];
    [RKObjectManager setSharedManager:manager];
    [RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:RKMIMETypeJSON];
    [manager.HTTPClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [manager registerRequestOperationClass:[AFJSONRequestOperation class]];
    [manager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
    [manager setRequestSerializationMIMEType:RKMIMETypeJSON];
    manager.managedObjectStore = store;
    

    接下来,我设置连接和响应描述符:

    NSManagedObjectContext *context = [AppDelegate managedObjectContext];
    NSDictionary *orgRels = [[NSEntityDescription entityForName:@"NWOrg" inManagedObjectContext:context] relationshipsByName];
    NSDictionary *positionRels = [[NSEntityDescription entityForName:@"NWPosition" inManagedObjectContext:context] relationshipsByName];
    // ...
    
    NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
    
    NSArray *orgConnections =
    @[[self connectionForRelation:@"positions" localKey:@"orgId" foreignKey:@"orgId" withRels:orgRels],
      [self connectionForRelation:@"workers" localKey:@"orgId" foreignKey:@"orgId" withRels:orgRels]];
    [manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:
        [self entityMappingForName:@"NWOrg" fromDictionary:@{@"orgId": @"orgId", @"orgName": @"orgName"} withKey:@"orgId" andConnections:orgConnections]
        method:RKRequestMethodAny pathPattern:@"api/orgservice/get" keyPath:nil statusCodes:statusCodes]];
    
    NSArray *positionConnections =
    @[[self connectionForRelation:@"org" localKey:@"orgId" foreignKey:@"orgId" withRels:positionRels],
      [self connectionForRelation:@"shifts" localKey:@"positionId" foreignKey:@"positionId" withRels:positionRels]];
    [manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:
        [self entityMappingForName:@"NWPosition" fromDictionary:@{@"positionId": @"positionId", @"orgId": @"orgId", @"name": @"positionName"} withKey:@"positionId" andConnections:positionConnections]
        method:RKRequestMethodAny pathPattern:@"api/positionservice/get" keyPath:nil statusCodes:statusCodes]];
    
    // ...
    

    然后,我能够完成简单的请求,并且效果很好:

    [manager postObject:nil path:@"api/shiftservice/get" parameters:@{@"workerIds": @[@1]}
        success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        NSLog(@"Loaded shifts: %d", [[mappingResult array] count]);
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"Failed to load shifts with error: %@", [error localizedDescription]);
    }];
    

    注意:这使用了一些辅助方法,我将在此处重现:

    - (RKConnectionDescription *)connectionForRelation:(NSString *)relation
        localKey:(NSString *)localKey foreignKey:(NSString *)foreignKey 
        withRels:(NSDictionary *)rels
    {
        return [[RKConnectionDescription alloc] initWithRelationship:rels[relation]
            attributes:@{localKey: foreignKey}];
    }
    
    - (RKEntityMapping *)entityMappingForName:(NSString *)name
        fromDictionary:(NSDictionary *)dict withKey:(NSString *)key
    {
        RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:name
            inManagedObjectStore:[AppDelegate managedObjectStore]];
        [mapping addAttributeMappingsFromDictionary:dict];
        mapping.assignsDefaultValueForMissingAttributes = YES;
        mapping.assignsNilForMissingRelationships = YES;
        mapping.identificationAttributes = @[key];
    
        return mapping;
    }
    
    - (RKEntityMapping *)entityMappingForName:(NSString *)name
        fromDictionary:(NSDictionary *)dict withKey:(NSString *)key
        andConnections:(NSArray *)connections
    {
        RKEntityMapping *mapping = [self entityMappingForName:name
            fromDictionary:dict withKey:key];
        for (RKConnectionDescription *connection in connections)
        {
            [mapping addConnection:connection];
        }
        return mapping;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-09
      相关资源
      最近更新 更多