Core Data NSSQLiteStoreType problem

  • Hi, all.

    I am developing a (non-document based) Core Data app and am facing
    a problem with saving data in NSSQLiteStoreType.

    The app has a subclass of NSManagedObject and can add to-many
    relationship
    through a custom accessor.

    @interface AClass : NSManagedObject
    {
    }
    - (void) addRelation: (NSManagedObject *) aManagedObject;
    @end

    - (void) addRelation: (NSManagedObject *) aManagedObject
    {
    NSSet * changedObjects = [[NSSet alloc] initWithObjects:
    &aManagedObject count:1];

    [self willChangeValueForKey: @"relation"
             withSetMutation: NSKeyValueUnionSetMutation
             usingObjects: changedObjects];

    [[self primitiveValueForKey: @"relation"] addObject: aManagedObject];

    [self didChangeValueForKey: @"relation"
             withSetMutation: NSKeyValueUnionSetMutation
             usingObjects: changedObjects];

    [changedObjects release];
    }

    The custom to-many accessor is the same code introduced in Listing 4
    of Managed Object Accessor Methods in Core Data Programming Guide.

    In my code, I add managed objects with this accessor and the objects
    are added and the to-many relation are established correctly.

    But once I save the data and close the app then restart it again,
    the objects themselves remain there but the relations of some objects
    disappear. (Not all, but some. The relation is not transient.)

    I was using NSSQLiteStoreType and when I changed it to NSXMLStoreType
    or NSBinaryStoreType, there was no problem and all the relations
    remained
    after the app was closed and restarted. All the other codes were the
    same.
    Just the behavior of NSSQLiteStoreType was different.

    I wonder why and when the relations once established disappear, only
    when
    I use NSSQLiteStoreType. Does the type need some extra code the other
    types
    don't need?

    I am using Xcode 3.0 on Leopard.

    Thank you.
  • On Nov 10, 2007, at 11:18 PM, <chataka...> wrote:

    > I am developing a (non-document based) Core Data app and am facing
    > a problem with saving data in NSSQLiteStoreType.
    >
    > The app has a subclass of NSManagedObject and can add to-many
    > relationship
    > through a custom accessor.

    > But once I save the data and close the app then restart it again,
    > the objects themselves remain there but the relations of some objects
    > disappear.

    Describe the relationship in more detail.  Specifically, what does its
    inverse look like?  If it's missing an inverse, or has a to-one
    inverse instead of a to-many inverse, that could easily explain what
    you're seeing; the implementation of your custom -addRelationship:
    method isn't the problem.

    That's not to say your -addRelationship: method is entirely correct.
    If you're going to implement  accessor methods for to-many
    relationships, you need to do so in a fashion that's compliant with
    Key-Value Coding.  Otherwise you run the risk of accidentally
    implementing something that matches up with what KVC expects, as -
    addRelationship: does, and your results may also be unpredictable.

    For Core Data, that means the accessor methods for to-many
    relationships need to follow this naming pattern -- which is the
    standard naming pattern for set KVC:

      For adding & removing one object from the relationship:
      - (void)add<Key>Object:(NSManagedObject *)object;
      - (void)remove<Key>Object:(NSManagedObject *)object;

      For adding & removing (union & minus) sets of objects to & from the
    relationship:
      - (void)add<Key>:(NSSet *)objects;
      - (void)remove<Key>:(NSSet *)objects;

      For intersecting sets of objects (optional) with what's in the
    relationship:
      - (void)intersect<Key>:(NSSet *)objects;

      For getting & setting the whole relationship at once (optional):
      - (NSSet *)<key>;
      - (void)set<Key>:(NSSet *)objects;

    This should be documented in the Key-Value Coding Programming Guide;
    it's also described in detailed comments in the <Foundation/
    NSKeyValueCoding.h> header file, as part of the comments for the -
    [NSObject(NSKeyValueCoding) mutableSetValueForKey:] method.  And it
    goes without saying that your relationship names for to-many
    relationships should generally be plural. :)

    What this gets you is that code outside your class can just say
    (assuming your relationship's name is "items")

      NSMutableSet *myItems = [myObject mutableSetValueForKey:@"items"];

    and then perform manipulations on myItems (e.g. -addObject:, -
    unionSet:, etc.) and it will modify the relationship through your
    methods automatically.

      -- Chris
  • Chris,
    Thank you for your response.

    > Describe the relationship in more detail.  Specifically, what does
    > its inverse look like?  If it's missing an inverse, or has a to-one
    > inverse instead of a to-many inverse, that could easily explain what
    > you're seeing;

    It doesn't have any inverse relationship. One entity(A) has a to-many
    relationship
    to another entity(B), but B doesn't have any relationship to A.

    I added B to A with the method and A had Bs before I closed the app.
    Then when I restart the app, some As have lost all Bs, while other As
    who
    haven't lost Bs have all Bs. All or nothing.

    But if having no inverse relationship is a problem, I suppose the
    behaviors of
    NSXMLStoreType and NSBinaryStoreType are the same.

    In my case, only NSSQLiteStoreType has this problem.

    > For Core Data, that means the accessor methods for to-many
    > relationships need to follow this naming pattern -- which is the
    > standard naming pattern for set KVC:

    Thank you, I corrected the method names.

    -Chataka
  • > It doesn't have any inverse relationship. One entity(A) has a to-many
    > relationship to another entity(B), but B doesn't have any
    > relationship to A.

    That's illegal.  If you try to build this on Leopard, you should
    receive a lot of warnings.  Add the inverse relationship.

    There's more in the archives about this.

    - Ben
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today