Problem with property inherited from parent entity

2019-08-30 05:48发布

问题:

I'm trying to keep traveling route in core data and here is my data model. I have entity Coordinate keeping latitude and longitude in double, then I created Locatable entity and make relation between these two entities.

Coordinate <-> Locatable

then I have POI entity inherited Locatable these POI representing my route. finally I have Destination entity inherited POI using as my destination point

Coordinate <-> Locatable
                   |
                   V
                  POI
                   |
                   V
               Destination

My Route class have points as one-to-many relation with these POI and destination as one-to-one with Destination. Problem occur when I try to get my POI collection for create route with MKPolylineView, when I call route.points I also get my destination point with those POI. I know core data create big Locatable for both POI and Destination, but this behavior isn't logically right my destination point shouldn't show up with points. Is this right behavior or I missing something.

Quite complicated to explain if I miss some important information please tell me.

Updated for more clarify

I have Route entity with one-to-one with Destination as destination and one-to-many with POI as points(which I using as my traveling path)

When I add destination

route.destination = destination_obj

it also show up in

route.points

which doesn't right because these two property serve two different purpose (one for making traveling path, another for pre calculate some data). Is this behavior have any document or explanation ?

Added small data model and code sample so every one can reproduce this Make 3 entity

Family 
- int generation
- parents as to-may relation to Parent and family as inverse
- child as to-one relation to Child and family as inverse
Parent
- String name
- family to-one relation to Family
Child : Parent

Here is my code

Family *fam;

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Family" inManagedObjectContext:self.managedObjectContext];

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];

NSArray *meters = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];

if ([meters count] > 0) {
    NSLog(@"found");
    fam = [meters lastObject];
    fam.generation = [NSNumber numberWithInt:[fam.generation intValue] + 1];
} else {
    NSLog(@"new");
    fam = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:self.managedObjectContext];
    fam.generation = [NSNumber numberWithInt:1];
    [self saveContext];
};
NSLog(@"There are %d paren", [fam.parents count]);
for (Parent *p in fam.parents) {
    NSLog(@"name : %@", p.name);
}
Child *child;
if (!fam.child) {
    child = [NSEntityDescription insertNewObjectForEntityForName:
             [[NSEntityDescription entityForName:@"Child" inManagedObjectContext:self.managedObjectContext] name]
                                          inManagedObjectContext:self.managedObjectContext];
    fam.child = child;
}
fam.child.name = [NSString stringWithFormat:@"child number %d", [fam.generation intValue]];
NSLog(@"There are %d parent after adding one child", [fam.parents count]);

Parent *parent = [NSEntityDescription insertNewObjectForEntityForName:
                  [[NSEntityDescription entityForName:@"Parent" inManagedObjectContext:self.managedObjectContext] name]
                                               inManagedObjectContext:self.managedObjectContext];
parent.name = [NSString stringWithFormat:@"parent number %d", [fam.generation intValue]];
[fam addParentsObject:parent];

NSLog(@"There are  %d parent after add parent", [fam.parents count]);
for (Parent *p in fam.parents) {
    NSLog(@"name : %@", p.name);
}

[self saveContext];

in short I create family and add one child and one parent to this family and print out some output in the first run I got this result

2011-08-27 19:06:28.271 child[2015:207] new
2011-08-27 19:06:28.276 child[2015:207] There are 0 paren
2011-08-27 19:06:28.278 child[2015:207] There are 0 parent after adding one child
2011-08-27 19:06:28.279 child[2015:207] There are  1 parent after add parent
2011-08-27 19:06:28.280 child[2015:207] name : parent number 1

which is what I expected, then I rerun the app again and this what the weird thing occur

2011-08-27 19:08:12.383 child[2035:207] found
2011-08-27 19:08:12.386 child[2035:207] There are 2 paren
2011-08-27 19:08:12.387 child[2035:207] name : parent number 1
2011-08-27 19:08:12.388 child[2035:207] name : child number 1
2011-08-27 19:08:12.389 child[2035:207] There are 2 parent after adding one child
2011-08-27 19:08:12.390 child[2035:207] There are  3 parent after add parent
2011-08-27 19:08:12.390 child[2035:207] name : parent number 1
2011-08-27 19:08:12.391 child[2035:207] name : parent number 2
2011-08-27 19:08:12.391 child[2035:207] name : child number 2

child entity is included in parents property. This is some kind of my misconception or this is a bug on SDK ?

回答1:

I think your setup is too complicated. Also, you set up your relationships a bit like sub-classes. But relationships and sub-classes are completely different concepts, and I think you might be mixing them up.

Here is what I propose:

Have an entity Location, with attributes latitude, longitude and name. Set latitude and longitude as non-optional, but name as optional. Now you have all the basic building blocks you need.

In your code you can define objects such as *POI of type Location, *destination of type Location and *startPoint of type Location. You can use the coordinates to calculate the shortest route for example. By setting the name you can make any Location into a POI. If you want names for non-POIs, create a boolean attribute isPOI.

Now, if you want to store specific travel routes, you can introduce an entity Route, with attributes like name, date etc. and a one-to-many relationship to Location. Note that you can not put the many Locations in any particular order with this scheme. However, what you could do is include two more one-to-one relationships to Location, one called startLocation and one destination.

If you really need a more complex description of itineraries in your core data model, you probably need another entity. You could call it TravelPoints with a many-to-one relationship to Route, a one-to-one relationship to Location and attributes like arrivalDate, timeStayed or departureDate, sequentialNumber (to indicated the order in Route), etc.

With this setup you should be able to go far with your project.