connection between NSManagedObjectModel and my .xcdatamodel file? - core-data

Archiving is easy, now concepts of CoreData are confusing me.
What's the connection between the declared NSManagedObjectModel and my actual xcdatamodel file?
I declared NSManagedObjectModel, NSManagedObjectContext and accordingly a NSPersistentStoreCoordinator, and connected all three of them. During this process, I didn't see any clue that the declared NSManagedObjectModel property had anything to do with my xcdatamodel file.
Only when I initiated a NSFetchRequest, I told it the name of my targeted entity, and which was my NSManagedObjectContext.
And that'll do it? I don't have to tell anyone the name of my xcdatamodel file, but only the name of the targeted entity? Does the NSFetchRequest have to search all my xcdatamodel files for the certain entity? What if I have two entities of same name in two different xcdatamodel?

When you build your app, the .xcdatamodel file is compiled to produce a .mom file, which is incorporated into the app bundle. The prefix remains unchanged so, "myApplication.xcdatamodel" is compiled to "myApplication.mom".
If you get the URL for this file in the bundle (for example using NSBundle's URLForResource:withExtension method) you can initialise your NSManagedObjectModel instance using initWithContentsOfURL. Alternatively, and this may explain the apparent absence of any connection, the NSManagedObjectModel instance can be created using mergedModelFromBundles class method, which uses ALL the models (.mom files) in the given bundle.

The NSManagedObjectModel is the object that represents the entities you create in the data model (the .xcdatamodeld). The data model editor is sort of like a source code editor, while the NSManagedObjectModel is the thing you have that represents the compiled model.
The NSManagedObjectModel contains references to all of the entities in the model, which are represented as instances of NSEntityDescription. The purpose of the model object is
So that Core Data can understand the persistent store file. The model tells Core Data what entities to expect.
So that Core Data operations like fetch requests can be configured to properly access the persistent store file-- only using entities that actually exist there, for example.
So that instances of NSManagedObject can be created to reflect entities from the data model.

Related

Default Method of Built-in Persistent Storage Type Of Core Data In Xcode

According to apple doc's Persistent Store Types and Behaviors, the built-in persistent store types of core data are
1. XML
2. Binary
3. SQLite
4. In Memory
My Question is,
Among these which is the default store type when we use core data model in xcode and how can we change it
Well, NSPersistentStore is an abstract base class. One of its four subclasses must be deliberately created in code. So, there is not really a default store type.
There is, however some template code which gets generated when you choose one of the New Project or New Target templates in Xcode. In the current version (Xcode 10), when you switch on the Use Core Data checkbox, you get in the AppDelegate implementation a lazy var persistentContainer property which provides a singleton NSPersistentContainer object. This is by default the store you will use in the new target. But what store type is that? Well, the persistent store(s) of a NSPersistentContainer are specified in its persistentStoreDescriptions array property. By default, this array contains one persistent store of type SQLite, backed by a file in the Application Support folder of your app's container. This is, in a round-about way, the default store type you asked about.
The procedure to change this store type is explained in the Discussion section of the documentation of NSPersistentContainer.persistentstoredescriptions.
So you see the default is actually in the Xcode Project Templates. To get what you want, you can place the code you wrote after reading that documentation into a new Project Template and add it to your ~/Library. You can either override one of the default Project Templates, or create your own with a new name. A basic example is given in this blog post by Jake Craige. If that is not enough for you, Keith Harrison has published a quite thorough reverse engineering of Xcode Project Templates.

Simperium & mogenerator convenience accessors

I'm using Simperium and mogenerator in my project. I've added SPManagedObject entity to the model and set that as the parent class for other entities. For each entity, mogenerator automatically creates a _<entityname>.h and _<entityname>.m file that has several convenience accessors. I've modified the mogenerator build script so each of these subclasses SPManagedObject instead of NSManagedObject. The entity classes simply import the corresponding _<entityname>.h file.
My problem is I'm getting runtime errors when using any of the convenience accessors. For example, for an entity with attribute of type Integer32 called myInteger, the class file property is NSNumber. Mogenerator creates an accessor named myIntegerValue. The errors I'm getting are that myIntegerValue is an unrecognized selector for SPManagedObject. I can work around this obviously but it seems to be indicative of a bigger problem. Any ideas? Thanks!
This kind of problem is most often the result of failing to configure the class name in the Core Data model editor. You may have a class Foo and an entity Foo but they don't automatically go together (they're not required to have the same name). If you don't do this, you get instances of NSManagedObject instead of instances of your subclass. And of course, NSManagedObject doesn't have those methods.
Select the entity in the model editor and look in the model inspector on the right. Make sure that the class name is configured.

Can't execute SharePoint BCS AssociationNavigator when my entity classes are in another assembly

I have a simple SharePoint 2010 BCS solution where I define two entities and a simple parent-child relationship between them. I happen to have entity classes (Parent and Child) in a separate assembly from my service classes (ParentService and ChildService). This doesn't seem to present a problem when using just Finder and SpecificFinder methods, but when I try to execute an AssociationNavigator method it fails. When my entity types are in the same assembly as the BCS model definition and associates service classes, the AssociationNavigator works fine. I am calling the AssociationNavigator like this:
var entity_instance_collection = new EntityInstanceCollection(1);
entity_instance_collection.Add(parent_entity_instance);
var association = (IAssociation)parent_entity.GetMethodInstance("ParentToChildAssociationNavigator", MethodInstanceType.AssociationNavigator);
var child_items = child_entity.FindAssociated(entity_instance_collection, association, lobi);
When the entity types are in a separate assembly, I get an InvalidMetadataObjectException when trying to execute FindAssociated:
Cannot load Type described by TypeDescriptor TypeName
'BdcModelProject2.BdcModel1.Parent, BdcModel1' on Parameter with Name
'parent' on Method with Name 'ReadItem' on Entity (External Content
Type) with Name 'Parent' in Namespace 'BdcModelProject2.BdcModel1'.
with this InnerException:
Could not load type 'BdcModelProject2.BdcModel1.Parent' from assembly
'BdcModelProject2, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=50bc5a1f7318bdeb'.
So, it seems that my app is just trying to load my entity types from the assembly where the BCS model is defined (BdcModelProject2) rather than the assembly where my entities are actually defined (ClassLibrary1). I have a few points of confusion about this:
I see that the BCS model has TypeName attributes in the TypeDescriptors that describe the types of the classes that implement the entity classes, but the Finder and SpecificFinder methods seem to function properly for me even when gibberish is supplied here, yet the AssociationNavigator fails to load the type. Why is this?
I don't see anywhere in the Visual Studio-generated bdcm file or in the MSDN docs for a TypeDescriptor that indicates where an assembly name can be specified for the entity types.
So, how can I use entity types in my BCS project when those entities are defined in a different assembly?
There are two possibilities here:
It does not find the dll
It finds an old version of the dll, that does not contain the new code that you are using
We have often had a problem that an old version is in the GAC. When a new version is installed in the bin directory, it just ignores it and continues using the version in the GAC. Then you delete the version in the GAC, but it still does not work, since it has cached the old version. Finally an IIS reset or a machine restart gets it working.
Short answer: Try and find an old version of the dll on the machine.
Edit
You could use a tool like Assembly Binding Log Viewer to track down the problem.
see: http://msdn.microsoft.com/en-us/library/e74a18c4(v=vs.90).aspx

Renaming Core Data class

I have an application that uses CoreData.
I previously had a class named Marker which was linked to the Marker entity in Core Data.
I renamed the Marker class to CoreDataMarker. So I created a new .xcdatamodel file with the new class name for the entity. Then I created a .xcmappingmodel and selected the old and the new .xcdatamodel files and it seemed to 'auto-setup' fine.
However, when I run my application it complains with: "Can't merge models with two different entities named 'Marker'". I understand that this happens, but I have no idea how to solve it.
Do you know how?
Thanks in advance!
You don't need a new xcdatamodel. Change the in the "Class" field in the entity description for your Marker entity to CoreDataMarker. That's all that's needed. The implementing class information does not require a schema migration.
And make sure ONLY the current version of the data model (latest xcdatamodel file) is included in target and mapping model file. It looks like putting other model files are being done automatically based on information from xcmappingmodel file.
It is unintuitive but this was what worked for me.

Accessing Aggregate Entities without Lazy Loading

I want to follow the DDD philosophy and not access entity objects of an aggregate directly. So, i have to call the root object to get the associated entity. But In other cases I dont always want every associated entity to load when the root is called. Is that the purpose of lazy loading?
How do I access entity objects through the root without loading all the associated objects everytime if i disable lazyloading feature of linq?
EDIT:
For example, If I have a Person as the Root Entity, and the Person has Name, Addresses and OwnedProperties. If I want to get a list of People so that I could display their names, I dont necvessarily want to load up Owned Properties every time on the call to the Repository. Conversely, on another page I may want to show a list of OwnedProperties, but do not want the other information to load with the call. what is the simple way of just calling the Person without the owned property entity other than creating a new person object without that owned properties?
I don't thinks that's possible without lazy loading.
Getting all data at once: Eager Loading
Getting data when accessed: Lazy Loading
According to your edit:
What I do in these situations, is create a 'View' class or a 'DTO' class which just contains the properties that I'm interested in.
For instance, I could have a 'PersonView' class which just has a Name property for instance.
Then, using my OR/M mapper (I use NHibernate), I create a HQL query (or Criteria query) which works on my 'Person' entity. Before I execute the query, I tell NHibernate that I want 'PersonView' objects as a result (I specify a projection). Then, NHibernate is smart enough to execute a query that only retrieves the columns that are necessary to populate the PersonView instances.
One way to avoid lazy loading is just using the object 'id'

Resources