RestKit POSTing вложенных управляемых объектов создает дубликаты

У меня возникли трудности с размещением NSManagedObject с вложенными NSManagedObject с RestKit. Похоже, что я получаю повторяющиеся записи для вложенных NSManagedObjects, вставленных в CoreData, когда возвращается POST. Вот снимок модели:

Модель

Вот JSON, который я размещаю:

{
  "actions": [], 
  "application": "Identify", 
  "createBy": "welcomed", 
  "createDt": "2014-04-11T16:26:15Z", 
  "description": null, 
  "externalId": null, 
  "groupId": "5", 
  "id": 0, 
  "images": [
    {
      "format": "JPEG", 
      "height": 200, 
      "id": 0, 
      "image": "/9j/4A..../Pv5n/9k=", 
      "status": "C", 
      "type": "MUGSHOT", 
      "width": 200
    }
  ], 
  "locked": null, 
  "modifyBy": null, 
  "modifyDt": null, 
  "priv": null
}

Вот JSON, который возвращается службой после POST:

{
"actions": [], 
  "application": "Identify", 
  "createBy": "welcomed", 
  "createDt": 1397233575000, 
  "description": null, 
  "externalId": null, 
  "groupId": "5", 
  "id": 11, 
  "images": [
    {
      "captureDevice": null, 
      "createBy": null, 
      "createDt": null, 
      "format": "JPEG", 
      "height": 200, 
      "id": 11, 
      "image": "/9j/4AAQSkZJR.../Pv5n/9k=", 
      "recordId": 11, 
      "status": "C", 
      "type": "MUGSHOT", 
      "width": 200
    }
  ], 
  "locked": false, 
  "modifyBy": null, 
  "modifyDt": null, 
  "priv": false
}

РЕДАКТИРОВАТЬ (я полагаю, это важно): вот отображение для WTSImage и WTSRecord:

RKEntityMapping *recordMapping = [RKEntityMapping mappingForEntityForName:@"WTSRecord" inManagedObjectStore:self.managedObjectStore];
    [recordMapping addAttributeMappingsFromDictionary:@{
                                                        @"id":@"dbId",
                                                        @"externalId":@"extId",
                                                        @"groupId":@"groupId",
                                                        @"application": @"application",
                                                        @"description": @"desc",
                                                        @"priv": @"priv",
                                                        @"locked": @"locked",
                                                        @"createBy": @"createBy",
                                                        @"createDt": @"createDt",
                                                        @"modifyBy": @"modifyBy",
                                                        @"modifyDt": @"modifyDt",
                                                        }];
    recordMapping.identificationAttributes = @[@"dbId"];

    //image mapping
    RKEntityMapping *imageMapping = [RKEntityMapping mappingForEntityForName:@"WTSImage" inManagedObjectStore:self.managedObjectStore];
    [imageMapping addAttributeMappingsFromDictionary:@{
                                                       @"id": @"dbId",
                                                       @"status": @"status",
                                                       @"type": @"type",
                                                       @"format": @"format",
                                                       @"width": @"width",
                                                       @"height": @"height",
                                                       @"image": @"base64Image"
                                                       }];

    imageMapping.identificationAttributes = @[@"dbId"];
    [recordMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"images" toKeyPath:@"images" withMapping:imageMapping]];

В следующем коде я создаю объекты NSManagedObjects и вызываю [RKObjectManager postObject:path:parameters:success:failure::

WTSRecord *record = [NSEntityDescription insertNewObjectForEntityForName:@"WTSRecord" inManagedObjectContext:self.managedObjectContext];
record.createBy = @"welcomed";
record.createDt = [NSDate date];
record.application = kWTSApplicationIdentify;
record.groupId = @"5";

WTSImage *image = [NSEntityDescription insertNewObjectForEntityForName:@"WTSImage" inManagedObjectContext:self.managedObjectContext];
image.height = [NSNumber numberWithFloat:mugshot.size.height];
image.width = [NSNumber numberWithFloat:mugshot.size.width];
image.imageData = UIImageJPEGRepresentation(imageData, 1.0);
image.type = kWTSCaptureTypeMugshot;
image.format = kWTSCaptureFormatJpeg;
image.status = kWTSCaptureStatusCaptured;

image.record = record;
[record addImagesObject:image];

RKObjectManager *manager = [RKObjectManager sharedManager];
[manager postObject:record path:@"records" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error Sending Record" message:error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }];

Когда вызывается блок успеха, я проверяю базу данных sqlite и обнаруживаю, что вставлена ​​1 запись WTSRecord и 2 WTSImages. Один из WTSImages имеет правильный FK для WTSRecord и PK из базы данных, в то время как другой кажется потерянным (dbId и FK для WTSRecord не установлены).

Вот ссылка на журналы трассировки RestKit и Core Data: https://dl.dropboxusercontent.com/u/466390/restkit2.txt

Надеюсь, кто-то сможет помочь! Спасибо!

ИЗМЕНИТЬ. После еще нескольких поисков я нашел эту страницу: https://github.com/RestKit/RestKit/issues/1228

Должен ли я создавать элементы идентификации на стороне клиента с использованием UUID перед их отправкой в ​​службу REST? Не сможет ли RestKit отобразить объекты запроса обратно на объекты, которые уже были созданы в хранилище объектов, без предварительной установки атрибута идентификации на стороне клиента?


person Dan    schedule 11.04.2014    source источник


Ответы (1)


Для отправленного объекта RestKit понимает, как обновить этот элемент данными ответа, но это не относится к содержимому отношений. Технически это можно было закодировать, но в настоящее время это не так.

Если вам нужно, чтобы объект в отношении после сопоставления был тем же объектом, который вы создаете, у вас есть проблема. Если вы не против того, чтобы это был другой объект, проблема заключается в том, чтобы удалить дубликат ...

Повторное удаление:

Блоки запроса на выборку не используются при обработке ответа POST, поэтому вам нужно получить дубликат и удалить его вручную. Я собираюсь предположить, что любое изображение с нулевым отношением к записи является обманом, поэтому его выборка относительно проста для выполнения.

person Wain    schedule 11.04.2014
comment
Большинство Apis, с которыми я работал, позволяют создавать контейнер изображений, требуя, чтобы сначала был создан контейнер, а затем несколько загрузок (по одной на изображение). Как правило, это лучше с точки зрения управления сетью и решит вашу проблему, так как каждый опубликованный объект будет обновлен так, как вы ожидаете. - person Wain; 12.04.2014
comment
Спасибо за информацию Wain! Вы, честно говоря, бог RestKit, и последние пару дней вы сэкономили мне столько времени своими ответами! Мне нравится ваше решение больше, чем использование пользовательских UUID (которые, как я обнаружил, могут обновлять вложенные управляемые объекты). Я бы предпочел не иметь дело с дополнительным уникальным идентификатором в базе данных, поэтому я думаю, что очистка любых изображений, имеющих нулевое отношение, - это лучший способ. Спасибо, что подтвердили ограничение с помощью RestKit, поэтому я могу перейти к фактической работе. :) - person Dan; 12.04.2014
comment
Привет @Wain, это все еще так? Мне нужно отправить кучу связанных объектов, которые уже существуют в базе данных, и я бы предпочел, чтобы они были сопоставлены так же, как и основной объект, и, таким образом, избежать дублирования. Большое спасибо! - person amcastror; 21.10.2016