I need to send an object (NSManagedObject (NSMO) subclass) up to a web service and retrieve it later. I was hoping I could somehow serialise it, but I'm hoping not to have to jump through the encoding hoops.
I can convert a simple NSMO object into a dictionary using:
[instance dictionaryWithValuesForKeys:instance.entity.attributesByName.allKeys];
However, my NSMO is a number of levels deep in terms of relationships to other NSMOs. What would be the best way to create a full serialised version of the object?
If you want to do this in a general way, you could write a recursive method serializedDictionary (either in a subclass of NSManagedObject or in a category) which:
Creates an empty NSMutableDictionary.
For each property, adds the key and value to the dictionary.
For each relationship, adds the relationship name as key and then calls serializedDictionary on the object and adds that as the value. If it's a to-many relationship, you'll have to put those values in an NSArray.
Note that if it's at all possible for a child object to be related back up to a parent (which is very possible if you have inverse relationships like Core Data recommends) you will either need to whitelist the relationships you save (easier) or pass along a set to keep track of which objects have already been serialized, so you don't encode them again (harder, I don't recommend this).
Related
I am using EF 4.1 and in a certain point in my application, I read all the data satisfying a condition from an entity by performing:
context.Entity.Where(<condition>)
then, I iterate over them through a loop, and in specific situations I store some of them into a Dictionary (key value is the Id of the entity, and value is the entire object).
Later, in another point of my app, I read all the objects stored in the dictionary and I update them.
After updating them, I perform SaveChanges on the context, (the context is the same that was used when reading the entire entity and when items where stored in the dictionary.
So at this point, I would like to know if when I perform the savechanges, the data is sent to the database and udpated correctly since I am not sure as the objects modified come from the dictionary and I do not know if EF is so intelligent to know it should update database.
The dictionary as well as the EF context hold references to the objects. As long as the context isn't disposed, it will be able to track the changes.
In other words, putting your entities in a Dictionary (or List or any other means of collection) has no influence on the entities and their context.
One of my domain models has an Enum property that I like to create a dropdown box for, but the EFContextProvide Metadata function doesn't automatically import the Enum Entity Type for me to access it, so I created a static dictionay of that I like to add to the Metadata Mapping, acting as a lookup table. How can I add Enum entity type, so I can call:
breeze.EntityManager.createEntity(myEnum,...)
right now, I get the following error:
Error: Unable to locate an 'Type' by the name: myEnum
Any suggestion?
UPDATE: (I just added the enumType info of the Metadata function call)
"enumType":{"name":"Plugins","isFlags":"false","underlyingType":"Int32","member":["name":"Custom","value":"0"},{"name":"PluginOfTypeA","value":"1"},{"name":"PluginOfTypeB","value":"2"}]}
Thanks #Jay for your response, I was set in the right direction. Here is what I can say about dealing with Enum:
I created a lookup list on the server that I can separately call, to populate the dropdown list. I have a regular array that I initialize on the success promise of the results, list this data.results[0].myEnumLookup and then on the Viewmodel, I access that property and set in to the ko.observableArray() so I can refer to it in my View. Make sure you set the value: property of the select tag, to the value of item.
But the problem with doing it this way was that at the Save time, it wasn't reading Enum value and it was treating it as just text, so it was failing, so
More robust solution:
In our application we happen to really benefit from having an Enum and their pre-compile value, since we are using those Enum Domain models in other POCO projects, so I ended creating an EF DbSet and proper table that will be populated with all of my Enums values and I can save them into the DB, so now we have the list of items in DB, and I created a single level of inheritance for Enums, so in my controller, I get a IQueryable method that will get all of those Enums, and in the breeze application, in my config file, I define the types of enums, and then I will populate lists of items based on different types in my config, so I can refer to it in my view and binding it to the ko.observableArray(). Also in my original class, I no longer refer to the Enum, I will create MyEnumId as well as virtual MyEnum property that will do the mapping automatically in my EF5 setup.
Lesson I learned, even though Enum in .NET4.5 & EF5 is possible to store and read back, but it's not very practical when it comes to SPA front-end technologies, so I prefer having the integer value, and just manage the enums outside of it.
Not entirely sure I understand the question. By 'Enum entity type' do you mean an 'EntityType' that only has a fixed number of possible instances? If so, you can simply query the entire collection of these entity/instances onto the client and add them directly into your static dictionary. Since, the collection is conceptually immutable, you can query this at the beginning of you session. Further, you should NEVER need to create an instance of any of these 'entity enums' because you can always extract them from your dictionary.
But maybe I'm not understanding your question.
I'm trying to get the hang of MVC architecture. Say I have a plist in which there are a list of persons and each person has a few attributes like name, address and photograph. Suppose
I want to display these details in a table view. The cell title would be the name, description would be the address and the image towards the left would be the photograph of the person.
One approach I could take is to load the plist in an array-of-dictionaries in my viewDidLoad: and then display them.
However, I want to adopt an Object Oriented method by creating 'Person' class. How do I go about doing the same in this case? I believe I could start by creating a 'Person' class with three attributes:Name, Address, Photograph. What next? I would need many instances of this 'Person' class right? How would I 'load' each instance with a corresponding Person entry from the plist? Should I create another class that does this 'loading'? Do people use Singleton class to achieve his?
Could someone share some sample sample code to illustrate this? Or maybe guide me to blogs/resources that talk about this?
Hmmm, I think you are over thinking this a bit. I would just create a class that would handle my person, in this case your 'Person' class.
I would simply store each person using Core Data. Then, when it's time to display them, I would just make a fetch request and store all person managed objects into an NSMutableArray (which simply handles arrays of objects). Then you can simply use the index value to display the numerous persons in your array in a tableView.
In summary I would:
1. For every person, create instance of Person.
2. Verify if person exists in my Core Data Person Entity.
3. If not, then insert into Core Data (the object will become an
NSManagedObject).
4. For displaying, simply do a fetch request to pull all persons in your
entity. Here I prefer to store the
results into an NSMutableArray, but
that is completely up to you. Make
sure you release your fetch request
after the results are store in the
array.
5. Reference them to your table view using the index value for each
person NSManagedObject in the array.
For something that doesn't involve storing simply:
1. Create instance of Person for every entry.
2. Add Person object to array.
3. Reference each Person to table view using index value.
In the end the approach that you take will be dictated by what you want to do with the information.
As for reading the plist, I would opt for reading an XML for which all you need is an XML Parser class (there are several options for parsers). Since I don't do anything but parse the XML, I use NSXMLParser, but that choice is also up to you. Just create an NSXMLParser class (make sure that the different actions for when the parser finds a given element are in play inside that parser). So yes, you would need to make additions to the NSXMLParser for handling each element. It's really easier than it sounds.
Also, by storing in Core Data, you can always fetch the info without you using a Singleton.
I believe you are not looking for a design solution to the above mentioned question. If that is the case #A Salcedo 's version looks fine.
if you are looking for general guide lines for MVC and modeling , Martin Fowler's site offers some of the best (agile) design/modeling guidelines.
http://www.martinfowler.com/eaaDev/uiArchs.html (on MVC) and
http://martinfowler.com/design.html (many interesting design related posts).
Happy reading.
Why would I need to use a primitive accessor methods in a core data project?
I'm reading about Core Data and note the below:
By default, Core Data dynamically
creates efficient public and primitive
get and set accessor methods for
modeled properties (attributes and
relationships) of managed object
classes...
For example, given an entity with an
attribute firstName, Core Data
automatically generates firstName,
setFirstName:, primitiveFirstName, and
setPrimitiveFirstName:.
I'm still not sure what the primitive accessor methods are? How do they work? When & why would I need to use them over the normal accessor methods?
thanks
In normal classes, you would not usually use primitive accessors, but Core Data uses them frequently. The most common scenario: You write a custom accessor (to perform maintenance, create a default object, handle transient wrapper of persistent property, etc.) but want to use Core Data's optimized storage. If the optimized accessors were normal accessors, your custom one would prevent it from being available, but instead you just have to use the primitive accessor.
Also, the default accessors you get from Xcode include methods to add or remove objects from to-many relationships. If these methods used normal accessors, the normal accessors would trigger change notifications for the entire set. Instead they use the primitive accessors and create their own change notifications for just the part they are changing.
The most important thing is that the primitive accessors are the only way to get to the optimized storage. Without them, you would have to use instance variables, which Apple advises against.
If you are writing your own methods in a subclass of NSManagedObject, the primitive accessors enable you to get directly at the data the object contains.
Effectively, you would use them the same way you would use an instance variable in a normal class.
The primary use of primitive accessors is to prevent key-value observing notifications from being sent when you change a value. Sometimes you do not want such notifications sent because they have quite a bit of overhead. E.g. when importing large sets of data or when you use a transitory value to alter a persisted value.
You use them almost always when writing customer accessor methods. If you look at the accessor methods generated by Xcode for managed object subclasses, you can see how they are used.
How to group methods belong to one entity in one class file in Core Data like Entity Framework?
In Linq, we can put all methods in the domain object class and reuse them, in Core Data, is there any way to create different classes for different entities? Or we can only use predicate to retrieve?
It seems that I can't define the class for each entity I configured in the data model. And it is not like hibernate that I can control the physical database schema via ORM. Correct me if I am wrong, I don't believe Core Data can do this as far I know.
So what is the advantage to use Core Data? And is there any mechanism on Cocoa that I can define my domain object classes including primary key, foreign key, for instance, and then create the database schema then?
It seems like the Core Data can only support configuring the objects but there is even no way to configure the physical database via the Core Data.
In your Core Data model you can define which class to instantiate your entities as:
alt text http://img404.imageshack.us/img404/3368/setclass.png
When Core Data fetches objects from the store, it will attempt to create them as instances of this class (although it's not quite that simple, Core Data does some tricks).
You can auto-generate class files for your entities by opening your core data model in a new window, and choosing File->New File:
alt text http://img241.imageshack.us/img241/8238/newfile.png
You should see a new "Managed Object Class" item:
alt text http://img46.imageshack.us/img46/348/managedobjectclass.png
Choose this and select the entities to generate classes for:
alt text http://img241.imageshack.us/img241/5030/selectentity.png
A class will be generated with various properties for getting/setting the attributes on your entity:
alt text http://img10.imageshack.us/img10/9868/generatedproperties.png
If you want to add your own methods, I would recommend you add them to a separate Category. This is because you will often want to regenerate these core data classes when you add new properties or change the entities. If you make additions directly to these files you will lose your changes the next time you generate them.
So create a category called Person+Additions or whatever name you think is appropriate:
alt text http://img294.imageshack.us/img294/8871/addcategory.png
And add any new methods or properties to this class:
alt text http://img717.imageshack.us/img717/3884/addmethods.png
Note that you cannot add new instance variables, but NSManagedObject has facilities to get/set values in an internal dictionary. See the NSManagedObject documentation
So once you've done all this, all you do is cast the NSManagedObject you get from a fetch request (or wherever) to the appropriate type:
#import "Person+Additions.h"
//...
Person *p = (Person *) [fetchResult objectAtIndex:0];
[p myCustomMethod];
//...
As for your other questions about primary keys, and interacting with the physical database, this isn't really what Core Data is designed to provide you. You should not think too much about the underlying database, Core Data is meant to be more high level than that. You define your model, and fetch objects through the API. Primary keys and othe "database-y" details like this are not exposed.
If you want full control over the database you should use the sqlite APIs. But I would say for the large majority of applications Core Data is the better choice.
Look at the docs for KVC ("key-value-coding"). You use key paths to obtain the values you want. You can also sort the data in an array using a key path. For that, take a look at NSSortDescriptors. Otherwise, yes, just change your NSPredicate and re-fetch.