IOS Coredata UNIQUE约束失败: [英] IOS Coredata UNIQUE constraint failed:

查看:444
本文介绍了IOS Coredata UNIQUE约束失败:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图插入数据到coredata,但我得到错误像,


CoreData:error:(1555)UNIQUE约束失败:ZSIDETABLENAME.Z_PK


场景: -



先从appdelegate。 m我将数据从我的SQL文件复制到文档目录的sql文件。

   - (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{
if(_persistentStoreCoordinator!= nil){
return _persistentStoreCoordinator;
}


//创建协调器并存储

NSString * from;
NSString * to;
NSArray * mainPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString * documentsDirectory = [mainPath objectAtIndex:0]; //获取文档文件夹
/*VoiceRecords.plist文件* /
from = [[NSBundle mainBundle] pathForResource:@NewsofType:@sqlite];
to = [documentsDirectory stringByAppendingPathComponent:@News.sqlite];
[[NSFileManager defaultManager] copyItemAtPath:from
toPath:to error:nil];
from = nil;
to = nil;

NSURL * storeURL = [[self applicationDocumentsDirectory] ​​URLByAppendingPathComponent:@News.sqlite];

NSError * error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if(![_ persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:& error]){
/ *
用代码来替换此实现以适当地处理错误。

abort()导致应用程序生成崩溃日志并终止。您不应在运送应用程序中使用此功能,但在开发过程中可能很有用。

此处的错误的典型原因包括:
*持久存储不可访问;
*持久存储的模式与当前管理对象模型不兼容。
检查错误消息以确定实际问题是什么。


如果永久存储不可访问,则文件路径通常有问题。通常,文件URL指向应用程序的资源目录,而不是可写目录。

如果在开发期间遇到模式不兼容性错误,可以通过以下方式减少它们的频率:
*简单地删除现有存储:
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil ]

*通过将以下字典作为options参数传递来执行自动轻量级迁移:
@ {NSMigratePersistentStoresAutomaticallyOption:@YES,NSInferMappingModelAutomaticallyOption:@YES}

轻量级迁移将只适用于有限的一组模式更改;有关详细信息,请参阅核心数据模型版本控制和数据迁移编程指南。

* /
NSLog(@未解析的错误%@,%@,错误,[错误userInfo]);
abort();
}

return _persistentStoreCoordinator;
}

它可以正常工作。然后我试图保存用户在mainviewcontroller.m中的coredata中输入的URL。

   - (void)feedParserDidFinish:(MWFeedParser * )parser {

NSFetchRequest * fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@IWorld];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@feedurl =%@,self.Feedlink];
NSManagedObjectContext * context = [self managedObjectContext];

if([[context executeFetchRequest:fetchRequest error:NULL] count] == 0){
NSError * error = nil;

NSPredicate * predicate = [NSPredicate predicateWithFormat:@feedurl contains%@,check];
[fetchRequest setPredicate:predicate];
NSMutableArray * checkp = [[context executeFetchRequest:fetchRequest error:& error] mutableCopy];


if(checkp.count <= 0){
NSManagedObject * newDevice = [NSEntityDescription insertNewObjectForEntityForName:@IWorldinManagedObjectContext:context];
[newDevice setValue:self.Name forKey:@name];
[newDevice setValue:self.WebsiteName forKey:@websitename];
[newDevice setValue:self.Feedlink forKey:@feedurl];

//将对象保存到持久存储
if(![context save:& error]){
NSLog(@无法保存!%@%@ ,error,[error localizedDescription]);
}
//保存lockbox中的值

NSArray * keys = [[[NewDevice entity] attributesByName] allKeys];
NSDictionary * dict = [newDevice dictionaryWithValuesForKeys:keys];

}

}


NSFetchRequest * fetchrequestforside = [NSFetchRequest fetchRequestWithEntityName:@Sidetablename]; // Sidetablename is entity
fetchrequestforside.predicate = [NSPredicate predicateWithFormat:@feedurl =%@,self.Feedlink];
NSManagedObjectContext * context = [self managedObjectContext];
if([[context executeFetchRequest:fetchrequestforside error:NULL] count] == 0){
//创建一个新的托管对象

NSError * error = nil;

NSPredicate * predicate = [NSPredicate predicateWithFormat:@feedurl contains%@,check]; // check is urlstring
[fetchrequestforside setPredicate:predicate];
NSMutableArray * checkp = [[context executeFetchRequest:fetchrequestforside error:& error] mutableCopy];


if(checkp.count <= 0)//如果coredata将找到url,然后不存储在coredata中else存储过程
{

NSManagedObject * newDevice1 = [NSEntityDescription insertNewObjectForEntityForName:@SidetablenameinManagedObjectContext:context];

if(self.Name)
{
[newDevice1 setValue:self.Name forKey:@name];


}
if(self.WebsiteName)
{
[newDevice1 setValue:self.WebsiteName forKey:@websitename];

}

if(self.Feedlink)
{
[newDevice1 setValue:self.Feedlink forKey:@feedurl];

}




NSError * error = nil;
if(![context save:& error]){
NSLog(@无法保存!%@%@,错误,[error localizedDescription]); //通过nslog获取错误// CoreData:错误:(1555)UNIQUE约束失败:ZSIDETABLENAME.Z_PK

}

有人请帮我吗?
注意: - 这一切都发生在第一次。第二次当我将运行应用程序所有工作正常。

解决方案

您在sidetablename表上得到主键约束违规。



因此,我相信你的问题是你如何创建和复制你的种子数据库。



不幸的是,你没有提供该信息。因此,我会猜测你是如何做到的。



我假设你使用mac应用程序创建数据库,或者你在iOS模拟器中。



由于WAL是iOS / OSX 7 / 10.9以来的默认模式,我假设你创建了您的种子数据库在WAL模式。这意味着您可能错过了-wal和-shm文件。如果您指定任何数据属性应使用外部存储,您也会错过该数据。



创建要复制的种子数据库时,您还需要复制-shm / wal文件,或者您需要以回滚日志模式创建数据库,这将在文件中添加所有数据。



您可以通过设置以下内容添加持久存储的选项(如果已经使用选项,只需将其与其他选项合并)。

  NSDictionary * options = @ {NSSQLitePragmasOption:@ {@journal_mode:@DELETE}}; 
if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:& error]){
/ /处理错误
}

这是如何在创建时添加持久存储要复制到捆绑包的数据库。它将确保一切都在实际的数据库文件中。



现在,运行你的代码创建你的种子文件后,你应该去那个目录,看看是否有是放置在周围的任何其他文件。最好的方法是在Terminal。转到该目录并执行ls -lat,它将列出按时间排序的所有文件。



注意:SQLite和Core Data创建额外的文件,sqlite文件,取决于两个实体的配置。因此,一般来说,您应该将每个核心数据持久存储视为一个文件包。换句话说,您应该为核心数据存储创建一个单独的目录。这样,当SQLite或核心数据决定创建额外的文件时,一切都只限于一个目录。



当您将文件复制到捆绑资源时,



同样,在部署时应该将所有内容从包复制到设备。

$但是,不要使用文件系统,应该考虑 NSPersistentStoreCoordinator ...上的这些方法...

  / *用于另存为 - 性能可能因旧版和
新商店的类型而异;旧的存储通常通过
迁移操作从协调器中删除,因此在
调用此方法之后不再是有用的参考
* /
- (NSPersistentStore *)migratePersistentStore :(NSPersistentStore *)store
toURL:(NSURL *)URL
options:(nullable NSDictionary *)options
withType:(NSString *)storeType
error: )错误;

/ *根据存储
类的要求复制或覆盖目标持久存储。重要的是传递类似的选项为
addPersistentStoreWithType:... SQLite存储将荣誉文件锁,日记
文件,日记模式和其他复杂性。其他商店将默认
使用NSFileManager。
* /
- (BOOL)replacePersistentStoreAtURL:(NSURL *)destinationURL
destinationOptions:(nullable NSDictionary *)destinationOptions
withPersistentStoreFromURL:(NSURL *)sourceURL
sourceOptions: (null null NSDictionary *)sourceOptions
storeType:(NSString *)storeType
error:(NSError **)error NS_AVAILABLE(10_11,9_0);






因此,我相信如果您创建数据库正确地,然后将其完全正确复制到您的资源束和应用程序,那么您的问题将消失。


I am trying to insert data into coredata but i am getting error like ,

CoreData: error: (1555) UNIQUE constraint failed: ZSIDETABLENAME.Z_PK

Scenario :-

First: from appdelegate.m I am copying data from my SQL file to document directory's sql file .

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }


   //  Create the coordinator and store

        NSString* from;
        NSString* to;
        NSArray* mainPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [mainPath objectAtIndex:0]; // Get documents folder
        /*VoiceRecords.plist file*/
        from=[[NSBundle mainBundle]pathForResource:@"News" ofType:@"sqlite"];
        to=[documentsDirectory stringByAppendingPathComponent:@"News.sqlite"];
        [[NSFileManager defaultManager]copyItemAtPath:from
                                               toPath:to error:nil];
        from=nil;
        to=nil;

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"News.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

         Typical reasons for an error here include:
         * The persistent store is not accessible;
         * The schema for the persistent store is incompatible with current managed object model.
         Check the error message to determine what the actual problem was.


         If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

         If you encounter schema incompatibility errors during development, you can reduce their frequency by:
         * Simply deleting the existing store:
         [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

         * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
         @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

It works correctly. Then i am trying to save url entered by user in coredata in mainviewcontroller.m.

- (void)feedParserDidFinish:(MWFeedParser *)parser {

        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"IWorld"];
                fetchRequest.predicate = [NSPredicate predicateWithFormat:@"feedurl = %@", self.Feedlink];
        NSManagedObjectContext *context = [self managedObjectContext];

      if ([[context executeFetchRequest:fetchRequest error:NULL] count] == 0) {
                NSError *error = nil;

            NSPredicate *predicate=[NSPredicate predicateWithFormat:@"feedurl contains %@",check];
            [fetchRequest setPredicate:predicate];
              NSMutableArray *checkp = [[context executeFetchRequest:fetchRequest error:&error]mutableCopy];


            if (checkp.count<=0) {
                NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:@"IWorld" inManagedObjectContext:context];
                [newDevice setValue:self.Name forKey:@"name"];
                [newDevice setValue:self.WebsiteName forKey:@"websitename"];
                [newDevice setValue:self.Feedlink forKey:@"feedurl"];

                                   // Save the object to persistent store
                if (![context save:&error]) {
                    NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
                }
                    //Save value in lockbox

                NSArray *keys = [[[newDevice entity] attributesByName] allKeys];
                NSDictionary *dict = [newDevice dictionaryWithValuesForKeys:keys];

            }

        }


     NSFetchRequest *fetchrequestforside=[NSFetchRequest fetchRequestWithEntityName:@"Sidetablename"]; //Sidetablename is entity
    fetchrequestforside.predicate=[NSPredicate predicateWithFormat:@"feedurl = %@", self.Feedlink];
             NSManagedObjectContext *context = [self managedObjectContext];
    if ([[context executeFetchRequest:fetchrequestforside error:NULL] count] == 0) {
                    // Create a new managed object

                    NSError *error = nil;

                    NSPredicate *predicate=[NSPredicate predicateWithFormat:@"feedurl contains %@",check ]; //check is urlstring
                    [fetchrequestforside setPredicate:predicate];
                    NSMutableArray *checkp = [[context executeFetchRequest:fetchrequestforside error:&error]mutableCopy];


                    if (checkp.count<=0) //if coredata will find url then notstore in coredata else stored procedure
          {

                    NSManagedObject *newDevice1 = [NSEntityDescription insertNewObjectForEntityForName:@"Sidetablename" inManagedObjectContext:context];

                    if (self.Name)
                    {
                        [newDevice1 setValue:self.Name forKey:@"name"];


                    }
                    if (self.WebsiteName)
                    {
                        [newDevice1 setValue:self.WebsiteName forKey:@"websitename"];

                    }

                    if (self.Feedlink)
                    {
                        [newDevice1 setValue:self.Feedlink forKey:@"feedurl"];

                    }




                    NSError *error = nil;
                    if (![context save:&error]) {
                            NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]); // Getting error here through nslog //CoreData: error: (1555) UNIQUE constraint failed: ZSIDETABLENAME.Z_PK

                        }

Someone please help me ? Note :- this all happen at first time. secondtime when i will run application all work correctly. don't know where is issue ?

解决方案

You are getting a primary key constraint violation on the sidetablename table.

Thus, I believe your problem is in how you created and are copying your seed database.

Unfortunately, you did not provide that information. Thus, I'll just guess as to how you did it.

I assume you created the database using a mac app or you did it in the iOS simulator. You then copied the sqlite file from wherever it was created into the bundle resources.

Since WAL has been the default mode since iOS/OSX 7/10.9, I assume you created your seed database in WAL mode. This means that you likely missed the -wal and -shm files. If you specified that any data attributes should use external storage, you missed that data as well.

When creating a seed database that you will copy, you need to also copy the -shm/wal files, or you need to create the database in rollback journal mode, which will have all added data in the file.

You do that by setting the following option when adding the persistent store (if you already use options, just incorporate this one in with the others).

NSDictionary *options = @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                              configuration:nil
                                                        URL:storeURL
                                                    options:options
                                                      error:&error]) {
    // Handle error
}

This is how you would add the persistent store when you are creating the database that you want to copy to the bundle. It will ensure that everything is in the actual database file.

Now, after you run your code to create your seed file, you should go to that directory and see if there are any other files laying around. The best way to do this is in Terminal. Go to that directory and do "ls -lat" which will list all files sorted by time.

Caveat: Both SQLite and Core Data can create extra files that go with the sqlite file, depending on configuration of both entities. Thus, you should, in general, treat each core data persistent store as a file package. In other words, you should create a separate directory just for the core data store. That way, when either SQLite or core data decides to create extra files, everything is confined to a single directory.

When you copy the files into the bundle resources, from where you created your seed database, you need to make sure you copy everything.

Likewise, you should copy everything from the bundle to the device when deploying.

However, instead of using the file system, you should consider these methods on NSPersistentStoreCoordinator...

/* Used for save as - performance may vary depending on the type of old and
   new store; the old store is usually removed from the coordinator by the
   migration operation, and therefore is no longer a useful reference after
   invoking this method
*/
- (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store
                                        toURL:(NSURL *)URL
                                      options:(nullable NSDictionary *)options
                                     withType:(NSString *)storeType
                                        error:(NSError **)error;

/* copy or overwrite the target persistent store in accordance with the store
   class's requirements.  It is important to pass similar options as
   addPersistentStoreWithType: ... SQLite stores will honor file locks, journal
   files, journaling modes, and other intricacies.  Other stores will default
   to using NSFileManager.
 */
- (BOOL)replacePersistentStoreAtURL:(NSURL *)destinationURL
                 destinationOptions:(nullable NSDictionary *)destinationOptions
         withPersistentStoreFromURL:(NSURL *)sourceURL
                      sourceOptions:(nullable NSDictionary *)sourceOptions
                          storeType:(NSString *)storeType
                              error:(NSError**)error NS_AVAILABLE(10_11, 9_0);


Thus, I believe that if you create your database properly, then copy it fully and properly to both your resource bundle and into your application, then your issues will go away.

这篇关于IOS Coredata UNIQUE约束失败:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆