Core data的batch update

文章介绍了在iOS8和OSX Yosemite中如何利用CoreData的NSBatchUpdateRequest进行批量更新操作,这种方法无需将所有实体加载到内存中即可进行更新,提高了效率并节省了内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于Core data最大的抱怨是缺乏批处理操作。比如RSS阅读器这种需要在众多entities上操作的应用,没有批处理操作就必须将所有东西装入内存,然后手动设置必要的attributes.

通常你会这么操作:

NSFetchRequest *fetchAllRSSItems = [NSFetchRequest fetchRequestWithEntityName:[RSSItem entityName]];
NSError *fetchError;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchAllRSSItems error:&fetchError];


if (results == nil) {
    NSLog(@"@"Error: %@", [fetchError localizedDescription]);  
} else {
    for (RSSItem *rssItem in results) {
        rssItem.read = [NSNumber numberWithBool:YES];
    }

    [self saveManagedObjectContext];


}

如果你使用一个主线程的managed object context, 你将会阻塞UI。你可以通过一个私有的managed object context来消除阻塞,但是这种操作仍然是耗时的。

在内存有限的设备,如iPhone上,将所有的entities放进内存甚至有可能做不到。为了解决内存问题,必须分批操作,但是这样做并不会加快操作。这种分批操作只好向用户显示一个进度条。

在iOS8和OS X Yosemite上,你再也不用将所有entities装进内存,手动设置attributes.

NSBatchUpdateRequest *batchRequest = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:[RSSItem entityName]];
batchRequest.propertiesToUpdate = @{NSStringFromSelector(@selector(read)):[NSNumber numberWithBool:YES]};
batchRequest.resultType = NSStatusOnlyRequestType; // NSStatusOnlyResultType is the default
batchRequest.affectedStores = @[...]; // Optional, stores this request should be sent to
batchRequest.predicate = [NSPredicate predicateWithFormat:@"..."]; // Optional, same type of predicate you use on NSFetchRequest

NSError *requestError;
NSBatchUpdateResult *result = (NSBatchUpdateResult *)[self.managedObjectContext executeRequest:batchRequest error:&requestError];

if (result == nil) {

    NSLog(@"Error: %@", [requestError localizedDescription]);
} else {

    // Batch update succeeded
}

当执行executeRequest:error:时,它将跨过managedObjectContext,直接update persistent store. 由于在context上没有任何改变的反映,所以该过程不会执行验证机制,所以必须小心。

如果需要在batch 操作完成之后update UI,那么可以讲batch request的resultType设为NSUpdatedObjectIDsResultType. 一旦有了IDs, 就可以通过主moc获取entities来更新UI.

如果并不关心实际的entities,而是想知道change是否发生,可以将resultType设置为NSUpdateObjectsCountResultType.当批处理完成之后,结果属性中会有一个NSNumber的变量存储改变的entities的数量。

转载于:https://www.cnblogs.com/lumouren009/p/4294307.html

09:45:58:967 引发的异常:“System.Data.Entity.Infrastructure.DbUpdateException”(位于 EntityFramework.dll 中) 09:45:58:967 System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.Entity.Core.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SQLite.SQLiteException: constraint failed 09:45:58:967 NOT NULL constraint failed: r2TabHistoryData.Batch 09:45:58:967 在 System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt) 09:45:58:967 在 System.Data.SQLite.SQLiteDataReader.NextResult() 09:45:58:967 在 System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave) 09:45:58:967 在 System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior) 09:45:58:967 在 System.Data.SQLite.SQLiteCommand.ExecuteDbDataReader(CommandBehavior behavior) 09:45:58:967 在 System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) 09:45:58:967 在 System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<>c.<Reader>b__6_0(DbCommand t, DbCommandInterceptionContext`1 c) 09:45:58:967 在 System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) 09:45:58:967 在 System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext) 09:45:58:967 在 System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior) 09:45:58:967 在 System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) 09:45:58:967 在 System.Data.Entity.Core.Mapping.Update.Internal.DynamicUpdateCommand.Execute(Dictionary`2 identifierValues, List`1 generatedValues) 09:45:58:967 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() 09:45:58:967 --- 内部异常堆栈跟踪的结尾 --- 09:45:58:967 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() 09:45:58:967 在 System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.<>c.<Update>b__21_0(UpdateTranslator ut) 09:45:58:967 在 System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update[T](T noChangesResult, Func`2 updateFunction) 09:45:58:967 在 System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update() 09:45:58:967 在 System.Data.Entity.Core.Objects.ObjectContext.<SaveChangesToStore>b__153_0() 09:45:58:967 在 System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) 09:45:58:967 在 System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction) 09:45:58:967 在 System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass148_0.<SaveChangesInternal>b__0() 09:45:58:967 在 System.Data.Entity.Infrastructure.DefaultExecutionStrategy.Execute[TResult](Func`1 operation) 09:45:58:967 在 System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction) 09:45:58:967 在 System.Data.Entity.Core.Objects.ObjectContext.SaveChanges(SaveOptions options) 09:45:58:967 在 System.Data.Entity.Internal.InternalContext.SaveChanges() 09:45:58:967 --- 内部异常堆栈跟踪的结尾 --- 09:45:58:967 在 System.Data.Entity.Internal.InternalContext.SaveChanges() 09:45:58:967 在 System.Data.Entity.Internal.LazyInternalContext.SaveChanges() 09:45:58:967 在 System.Data.Entity.DbContext.SaveChanges() 09:45:58:967 在 Asd.AgingTestRack.IMP.DB.ASD_AgingRack_db.SaveChanges() 位置 C:\Users\asd\Desktop\调试\Asd.AgingTestRack\Asd.AgingTestRack.IMP.DB\ASD_AgingRack_db.cs:行号 55: Database update error during SaveChanges. 分析错误
06-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值