核心数据需要时间来插入具有获取实体的记录并设置为关系

Posted

技术标签:

【中文标题】核心数据需要时间来插入具有获取实体的记录并设置为关系【英文标题】:Core data taking time to insert records with fetching entity & set as relationship 【发布时间】:2020-05-29 14:04:44 【问题描述】:

我有 2 个实体:具有一对多关系的组件和 SurveyReadingWeb。 我已将组件数据保存在核心数据数据库中;但是在保存 SurveyReadingWeb 时——在 for 循环中——我必须通过传递组件 id 并设置surveyreadings isComponentexists 关系来获取组件数据实体,如下面的代码中的8000条记录。这个过程花费了太多时间,将近 7 分钟。如何减少时间?

for item in items 
            autoIncrementId = autoIncrementId + 1
            print("reading items parsed:- \(item.SurveyReadingId), \(autoIncrementId)")

            let reading : SurveyReadingWeb? = NSEntityDescription.insertNewObject(forEntityName: Constants.EntityNames.kSURVEYREADINGWEB, into: self.managedContext) as? SurveyReadingWeb
            reading?.surveyId1 = Int32(autoIncrementId)
            reading?.surveyId = Int32(item.SurveyId) ?? 0
            reading?.readingData = item.CH4
            reading?.surveyDateTime = item.SurveyReadingDateTime
            reading?.latitude = item.Latitude
            reading?.longitude = item.Longitude
            reading?.serialNumber = item.SerialNumber
            reading?.descriptionText = item.Description
            reading?.componentName = item.Description
            reading?.componentId = Int32(item.ComponentId) ?? 0
            reading?.readingTypeId = Int32(item.ReadingTypeID) ?? 0
            reading?.readingTypeDetails = item.ReadingTypeDetails

            reading?.currentLatitude = item.CurrentLatitude
            reading?.currentLongitude = item.CurrentLongitude
            reading?.hdop = item.HDOP
            reading?.vdop = item.VDOP
            reading?.componentDistance = item.ComponentDistance
            reading?.facilityId = Int32(item.ProjectId) ?? 0
            reading?.posted = 1
            reading?.readyToSync = 1

            reading?.isComponentExists = DatabaseManager.sharedManager.getCompNameFromID(compID: Int32(item.ComponentId) ?? 0)
        
        saveContext()


func getCompNameFromID(compID : Int32) -> Components? 
    var component : Components? = nil
    let fetchRequest : NSFetchRequest<Components> = Components.fetchRequest()
    fetchRequest.predicate = NSPredicate(format: "componentId == %ld", compID)

    do 
        let searchResults = try managedContext.fetch(fetchRequest)
        component =  (searchResults.first) ?? nil
     catch 
    
    return component ?? nil

【问题讨论】:

【参考方案1】:

如果您将NSCache 实例添加到缓存compID:Components 键值对,则可以显着减少时间。

getCompNameFromID 中检查compID 是否存在于缓存中。如果是,则从缓存中获取值(非常快),如果不是,则获取记录并将其保存到缓存中的compID

并使用方便的 SurveyReadingWeb(context: 初始化器来消除所有难看的问号,但是性能优势相当小。

【讨论】:

您能否提供添加 NSCache 的代码?我已经添加了这种方式。它会工作吗?它会缓存所有 componentid 还是覆盖值? let cache = NSCache() cache.setValue(component?.componentId, forKey: "CachedComponent") NSCache 就像字典一样工作。键应该是标识符 (componentId),对应的值是 component 对象。使用setObject(_:forKey:) 设置键值对并使用object(forKey:) 读取它。不要使用 KVC 方法。

以上是关于核心数据需要时间来插入具有获取实体的记录并设置为关系的主要内容,如果未能解决你的问题,请参考以下文章

无法获取具有 SQL 等条件的核心数据

具有两个不同核心数据 NSManagedObject 实体的 NSTreeController

使用 JPA 获取最后插入记录的主键

仅在父子实体具有 1 到 M 关系的核心数据中获取父实体的数据

通过 linq 对实体查询进行分组,以通过加入表来获取具有最新时间戳的一条记录

核心数据获取请求不返回不同的结果