我正在处理的应用程序必须通过Web服务调用与数据库保持同步。
您最初必须插入大约300,000条记录,这需要花费大量时间。初始下载后,它会调用更新Web服务以获取所有已更改的记录。
在更新调用期间,我必须首先查看该对象是否已存在,这确实会降低该更新过程的速度。通常在早上有大约5k的记录要更新,这几乎与简单地插入300k记录一样长。
代码如下。有更快,更有效的方法吗?
code in loop when iterating through JSON records from server
if(isUpdating)
{
CaseStatusCode *oldObj = [CaseStatusCode doesExist:[record valueForKey:@"JSONData"] uid:[record valueForKey:@"RecordUID"] inContext:temporaryContext];
if(oldObj) //it exists
{
[oldObj initWithJSONSting:[record valueForKey:@"JSONData"]];
}
else //create new
{
NSEntityDescription *desc = [NSEntityDescription entityForName:NSStringFromClass([CaseStatusCode class]) inManagedObjectContext:temporaryContext];
CaseStatusCode *worker = [[CaseStatusCode alloc] initWithEntity:desc insertIntoManagedObjectContext:temporaryContext];
[worker initWithJSONSting:[record valueForKey:@"JSONData"]];
}
}
确实存在功能
+ (CaseStatusCode *)doesExist:(NSString *)jsonString uid:(NSString *)uid inContext:(NSManagedObjectContext *)moc
{
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSError *e;
NSDictionary *jsonObj = [parser objectWithString:jsonString error:&e];
if(uid || NULL_TO_NIL([jsonObj valueForKey:@"CaseStatusCodeUID"]))
{
if(jsonObj)
{
uid = [jsonObj valueForKey:@"CaseStatusCodeUID"];
}
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[self entityName]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"caseStatusCodeUID ==[cd] %@", uid]];
[fetchRequest setFetchLimit:1];
NSError *error = nil;
if ([moc countForFetchRequest:fetchRequest error:&error] == 0) {
NSLog(@"!!!WARN: NO Object Matches for pred: %@", fetchRequest.predicate);
return nil;
}
else
{
// fetch your object
CaseStatusCode *result = [[moc executeFetchRequest:fetchRequest error:&error] lastObject];
if (error != nil) {
NSLog(@"ERROR: %@ %@", [error localizedDescription], [error userInfo]);
return nil;
}
return result;
}
}
return nil;
}
初始化代码
- (void)initWithJSONSting:(NSString *)jsonString
{
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSError *e;
NSDictionary *jsonObj = [parser objectWithString:jsonString error:&e];
if(e)
{
NSLog(@"JSON Error Creating State: %@", [e localizedDescription]);
}
else
{
MySingleton *globals = [MySingleton sharedInstance];
self.token = globals.token;
self.CaseStatusCodeUID = NULL_TO_NIL([jsonObj valueForKey:@"CaseStatusCodeUID"]);
self.CaseStatusCode = NULL_TO_NIL([jsonObj valueForKey:@"CaseStatusCode"]);
self.Active = NULL_TO_NIL([jsonObj valueForKey:@"Active"]);
self.desc = NULL_TO_NIL([jsonObj valueForKey:@"Description"]);
self.BaseStatus = NULL_TO_NIL([jsonObj valueForKey:@"BaseStatus"]);
}
}
感谢。
EDIT 我试图跟随苹果的例子。我正在构建一个UID的NSArray,然后使用IN谓词构建一个获取请求。我得到0结果,并且我验证了具有该UID的那种类型的对象。
uidArray = (NSMutableArray *)[uidArray sortedArrayUsingSelector:@selector(compare:)];
viewName = @"CaseStatusCode";
uidKey = @"caseStatusCodeUID";
// create the fetch request to get all CaseStatusCode matching the IDs
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:viewName inManagedObjectContext:temporaryContext]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat: @"%@ IN %@",uidKey, uidArray]];
// Make sure the results are sorted as well.
[fetchRequest setSortDescriptors:@[ [[NSSortDescriptor alloc] initWithKey:uidKey ascending:YES] ]];
// Execute the fetch.
NSError *error;
NSArray *matchingObjectsArray = [temporaryContext executeFetchRequest:fetchRequest error:&error];
NSLog(@"fetchRequest: %@", fetchRequest.description);
NSLog(@"# RECORDS TO UPDATE: %d",matchingObjectsArray.count );
下面是生成的FetchRequest:
<NSFetchRequest: 0x1f5d69d0> (entity: CaseStatusCode; predicate: ("caseStatusCodeUID" IN {"ef236614-aaa2-49ae-8713-fd4847948498"}); sortDescriptors: ((
"(caseStatusCodeUID, ascending, compare:)"
)); type: NSManagedObjectResultType; )
就像我说的那样,带有该UID的caseStatusCode确实存在。另外,如果我没有设置谓词,我会得到所有的CaseStatusCodes,所以我知道fetch正在运行..谓词只有一些。
好的,我上面是愚蠢的,正确的谓词格式使用%K:
[fetchRequest setPredicate: [NSPredicate predicateWithFormat: @"%K IN %@",uidKey, uidArray]];
迭代idArray和resultsArray的最佳方法是什么?即
最终得到两个已排序的数组 - 一个传递了员工ID 到获取请求,以及与匹配的托管对象之一 他们。要处理它们,您可以按照这些列表查看已排序的列表 步骤进行:
- 获取下一个ID和员工。如果ID与员工ID不匹配, 为该ID创建一个新的Employee。
- 获取下一位员工:如果是ID 匹配,移动到下一个ID和员工。
醇>
答案 0 :(得分:2)
我建议您阅读此Implementing Find-or-Create Efficiently声音,看看这是您正在使用的区域。
答案 1 :(得分:1)
考虑循环遍历所有JSON对象以收集所有CaseStatusCodeUID,然后在单个获取请求中获取它们。
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"caseStatusCodeUID IN[cd] %@", uidArray]];
然后遍历结果。