【问题标题】:Core data Migration Delete data of entity核心数据迁移删除实体数据
【发布时间】:2015-10-09 03:50:44
【问题描述】:

我想在核心数据中进行轻量级迁移。我正在为运行良好的实体添加一个属性。

但我希望在此特定迁移之后删除该实体的数据(该实体表中包含的所有对象)。

我经历了这个question,但这个方法看起来不太好,因为我想将未来需要的每个迁移的逻辑分开。

我想到了一种直接重命名该实体但未指定 rename Identifier 的方法,以便核心数据将其作为删除实体和添加新实体来处理,但这不会成为永久解决方案未来迁移中的所有类似案例。

如果我可以通过xcdatamodeld的UI直接删除数据,有什么办法吗?或者还有其他方法吗?

【问题讨论】:

    标签: ios core-data core-data-migration xcdatamodel


    【解决方案1】:

    我能够做到这一点,在寻找方法感到非常沮丧之后,通过映射模型使用自定义 EntityMigrationPolicy,为实体映射设置自定义策略,例如。 EntityNameToEntityName,对此政策 (ProductName.DeleteEntityPolicy):

    // Swift 5
    class DeleteEntityPolicy: NSEntityMigrationPolicy {
        override func begin(_ mapping: NSEntityMapping, with manager: NSMigrationManager) throws {
            // Get all current entities and delete them before mapping begins
            let entityName = "EntityName"
            let request = NSFetchRequest<NSManagedObject>(entityName: entityName)
            let context = manager.sourceContext
            let results = try context.fetch(request)
            results.forEach(context.delete)
            try super.begin(mapping, with: manager)
        }
    }
    

    有关使用映射模型设置自定义迁移的方法的更多信息:https://stackoverflow.com/a/40662940

    很想知道是否有更好的方法/内置方法来做到这一点。

    【讨论】:

    • 看来我找到了更简单的方法stackoverflow.com/a/63612829/2830525
    • 错误:(8)尝试写入只读数据库CoreData:错误:(8)尝试写入只读数据库错误:SQL执行期间executeBatchDeleteRequest错误导致未处理错误:尝试写入只读数据库和userInfo { NSFilePath = ".....sqlite3"; NSSQLiteErrorDomain = 8; } 对我来说它不起作用
    【解决方案2】:

    您可以使用映射模型来做到这一点。要创建映射模型,请按以下步骤操作:

    在 XCode 中选择新文件

    为您的新文件选择一个模板:在左侧窗格中选择 Core Data,在右侧窗格中选择 Mapping Model,然后单击 Next

    映射模型源数据模型:选择您的旧数据模型并点击下一步

    映射模型目标数据模型:选择您的新数据模型并点击下一步

    另存为:您可能知道这是如何工作的

    在您的映射模型中,您会在左侧看到一个名为“实体映射”的面板。选择您不想迁移的实体的实体映射,然后键入退格键将其删除。

    要使用映射模型自动迁移,您必须使用 NSMigratePersistentStoresAutomaticallyOption 和 NSInferMappingModelAutomaticallyOption 选项配置 Persistent Store Coordinator。

    【讨论】:

    • 感谢您的建议,能否详细说明您的答案?
    【解决方案3】:

    无需修改自动迁移的简单、“轻量级”解决方案就是确定是否发生了迁移(例如,通过NSUserDefaults 版本字符串),然后删除您想要删除的所有实体。

    如果没有关系,请考虑NSBatchDeleteRequest,这确实很有效。但是,在迁移后首次启动应用程序后,通过对象图删除也是可行的:获取实体的所有实例并遍历结果以删除每个实例,最后或批量保存。

    如果您需要有关性能的建议,请在 cmets 中与我联系。

    【讨论】:

      【解决方案4】:

      我发现了一种更简单的方法来跳过特定实体的迁移,而无需从映射模型中删除映射(如果实体之间存在复杂的关系,这可能会导致映射模型无效)。

      这个想法是一个什么都不做并成功验证迁移步骤的迁移策略:

      斯威夫特:

      import CoreData
      
      final class DeleteEntityMigrationPolicy: NSEntityMigrationPolicy {
          override func createDestinationInstances(forSource sInstance: NSManagedObject,
                                                   in mapping: NSEntityMapping,
                                                   manager: NSMigrationManager) throws { }
          
          override func createRelationships(forDestination dInstance: NSManagedObject,
                                            in mapping: NSEntityMapping,
                                            manager: NSMigrationManager) throws { }
          
          override func performCustomValidation(forMapping mapping: NSEntityMapping,
                                                manager: NSMigrationManager) throws { }
      }
      

      目标-C:

      // DSDeleteEntityMigrationPolicy.h
      
      #import <CoreData/CoreData.h>
      
      @interface DSDeleteEntityMigrationPolicy : NSEntityMigrationPolicy
      
      @end
      
      // DSDeleteEntityMigrationPolicy.m
      
      #import "DSDeleteEntityMigrationPolicy.h"
      
      @implementation DSDeleteEntityMigrationPolicy
      
      - (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
                                            entityMapping:(NSEntityMapping *)mapping
                                                  manager:(NSMigrationManager *)manager
                                                    error:(NSError *__autoreleasing  _Nullable *)error {
          return YES;
      }
      
      - (BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance
                                          entityMapping:(NSEntityMapping *)mapping
                                                manager:(NSMigrationManager *)manager
                                                  error:(NSError *__autoreleasing  _Nullable *)error {
          return YES;
      }
      
      - (BOOL)performCustomValidationForEntityMapping:(NSEntityMapping *)mapping
                                              manager:(NSMigrationManager *)manager
                                                error:(NSError *__autoreleasing  _Nullable *)error {
          return YES;
      }
      
      @end
      
      

      【讨论】:

        猜你喜欢
        • 2019-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-22
        • 1970-01-01
        • 2011-09-14
        • 1970-01-01
        • 2018-10-13
        相关资源
        最近更新 更多