I'm building an iPad application where I need user to create entity dynamically. I'm already having 3 entities which program uses.
Could you help me with code how to do it?
I want to understand the whole structure according to my understanding I have to create new managedObjectModel, add new entities and than merge it with existing one, is it correct?
While it is possible to create a new entity and a new model on the fly in practice this is massively complex. If nothing else you would have to migrate any existing persisted data to the new model and a new persistent store file. I strongly recommend against attempting this especially if you are just starting out with Core Data.
You do have options:
Firstly, are you sure you actually need a new entity? People just starting out with Core Data often mistake entities for managed objects. Entities are to managed objects as classes are to instances. Entities are abstractions used to create the object graph. They don't actually contain data. The times when you need new entities are very,very rare.
Secondly, if you do need some kind of dynamic entity, it would usually be best to decompose the dynamic entity into numerous fixed subentities and then use relationships to create a virtual entity. E.g. you need a dynamic Person "entity" so you create several entities in the model each of which holds one attribute of the person. You could have a Field entity which would have a fieldName attribute and then a fieldValue attribute. Then have a an actual Person entity that has no attributes but just relationships to the necessary Field objects. You could add any fields needed to any person and then reconstitute an virtual person object by walking the relationships to its fields.
I rather doubt however that you need that kind of flexibility. Such a need is very rare. I would step back and see exactly what dynamic data you think the user might need to enter.
That's correct -- you'd create an array of NSEntityDescription objects, then call setEntities: on the new managed object model. Then, finally, you'd merge that model with your built-in model.
But note that you can't change a model once it has been used to create a managed object context (or used for storage). You'll need to create new storage and context after the model is changed.
Related
I have a database model that can be modify by users at runtime:
adding new columns to existing tables
adding new tables
I want to use Entity Framework Core to access such model.
I'm able of creating the types for the new tables and fields using reflection but I'm not able of creating the DbSet members inside the DbContext class for these new types as the DbSet needs to know the type at compile time.
Does anyone know if this is something that can be achieved with EF Core?
A way of injecting the type to the DbSet member dynamically?
It sounds pretty weird to me that the users are the ones defining the tables and their columns, relationships, etc on runtime. Probably what you actually need is to have a structure of tables to support dynamic data, which is much more manageable, that is, a table that defines the UserModels, another table that defines the properties of those models, etc. That will vary a lot depending on your needs.
You could also consider using some special properties like XML data-type fields as suggested here: Dynamically adding a property to an entity framework object
I have a domain model architecture in which my domain/business objects were created based on the problem domain and independent of any knowledge of the physical data model or persistence structures. So far I'm on track because it's perfectly acceptable and often the case that there is an impedance mismatch between the domain model and the data model. A DBA created the database for getting the data they required, but it does not encapsulate the applications entire domain model or design.
The result - I have my own set of domain model objects. However all of the fields that need to be persisted do exist somewhere or another within my domain model, but not necessarily in the shape that my auto generated .edmx POCO entities have them. So I have all the data, it's just not in the perfect shape exactly like the tables in which auto generated POCO entities are created from.
I have seen a few posts on this topic like converting POCO entity to business entity and Entity Framework 4 with Existing Domain Model that make statements like the following:
"Create the entities in your entity data model with the same names as
your domain classes. The entity properties should also have the same
names and types as in the domain classes"
What!? No way, why should I have to make my domain model be reshaped to POCOs that are modeled exactly after the data model / table structure in the database? For example - in my case of having 5 given properties, 2 might be in class 'A' and 3 in class 'B', whereas a auto generated POCO class has all 5 in its own class 'A'.
This is the entire point, I want separation of my object model and data model but yet still use an ORM like EF 5.0 to map in between them. I do not want to have to create and shape classes and properties named as such in the data model.
Right now my .edmx in EF 5.0 is generating the POCO classes for me, but my question is how to dissolve these and rewire everything to my domain objects that contain all this data but just in a different shape?
By the way any solution proposed using a Code First approach is not an option so please do not offer this. I need some guidance or a tutorial (best) using EF5 (if possible because EF4 examples are always inheriting POCOs from ObjectContext) with wiring up my own business objects to the .edmx.
Any help or guidance is appreciated, thanks!
This sounds like exactly the use case of Entity Framework. I am making a few assumptions here. First that when you make this statement:
"I have a domain model architecture in which my domain/business objects were created based on the problem domain and independent of any knowledge of the physical data model or persistence structures."
That you mean this domain was created in the EF designer? But then you say:
"However all of the fields that need to be persisted do exist somewhere or another within my domain model, but not necessarily in the shape that my auto generated .edmx POCO entities have them."
This sounds to me like my first assumption is incorrect.
Next, you dismiss code first? If your domain model/business objects are code based and you want to persist them to a relational database, that is exactly the use case for code first. You have the code, now you need to create your DbContext and map it to your physical model.
However you dismiss that... so some thoughts:
If you have a domain model of code based business objects and you have an EDMX that is used for other things I think you would want to create a repository layer that uses something like auto mapper or manual projections to query your Entities and return your business objects.
If you have a domain model of code based business objects and you have an EDMX that is not used for other things other than persisting your business objects I would say that you need to express your domain in an EDMX and then map it onto your existing database. This is really the use case for an ORM. Having two domain models and mapping from one model to the other where one model matches your domain and one matches your database is adding an extra un-needed layer of plumbing.
The latter approach above is what is called "Model First" in EF parlance. There are several articles written about it although the bulk of them just generate the db from the model. You would not do that step, rather you would map your entities onto your existing database.
The basic steps for this are to "update from the database" not selecting any of the db objects (or entities would be created). Or, you can take your exiting .edmx in the designer (which is sounds like you have) and modify the entities to match your business domain. Or just delete all the entities in your EDMX model, create your entities as you want them, and then map them all.
Here is a jing I made where I use the EF Designer to bring in the model store (the only way to do this is to allow it to generate entities) and then delete the entities allowing the Store information to stay by clicking NO when it asks if you want to delete the table info.
http://screencast.com/t/8eiPg2kcp
I didn't add the POCO generator to this, but if I did it would generate the Entities in the designer as POCO classes.
The statement quoted above is not suggesting that you rewrite your domain objects to match your pocos, it is suggesting that you update the edmx to match your domain model.
In your example you could create an entity in your edmx that maps all 5 properties from both tables and EF will manage the mapping to and from the single generated Poco onto your tables.
Of course this means that you then have duplicate domain objects and pocos, meaning you would either have to manually convert your domain objects to pocos when interacting with EF,
or you could define your domain data objects as interfaces and provide partial implementations of the pocos that essentially identify each poco as being a concrete implementation of a domain object.
There are probably several other ways to skin this particular cat, but I don't think that you can provide predefined c# objects for use in an edmx.
One approach might be to select into a ViewModel (suited to your particular business logic) and automatically map some data from the context into it like so https://stackoverflow.com/a/8588843/201648. This uses AutoMapper to map entity properties from an EF context into a ViewModel. This won't do everything for you, but it might make life a bit easier. If you're unhappy with the way this occurs automatically, you can configure AutoMapper to do things a bit differently (see Projection) - https://github.com/AutoMapper/AutoMapper/wiki/Projection
You might know this already, but its also possible to automatically generate POCOs from your EDMX using t4 - http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d. If you define the templates to generate partial classes, you can then have another partial class with your custom properties for that POCO. That way you can have most properties automatically populated, but have other custom properties which you populate with custom rules from your context/repository. This takes a lot of the monotony out of generating these, and you can then focus on reshaping the data using the above technique.
If you're seriously unhappy with both, you could always map a stored procedure to get the exact field names that you want automatically without needing to stuff around. This will of course affect how you work with the data, but I have done it before for optimisation purposes/where a procedure already existed that did exactly what I wanted. See http://msdn.microsoft.com/en-us/data/gg699321.aspx
Can Core Data allow me to create new table programmatically? or if I need that I need to use SQLite directly.
thanks
From a CoreData perspective, you don't really create new tables because database tables are only one possible type of persistence store associated with the core data model.
You can, however, create new core data entities programatically using the NSEntityDescription class. In the NSEntityDescription class documentation you will find this:
Entity descriptions are editable until they are used by an object graph manager. This
allows you to create or modify them dynamically. However, once a description is used
(when the managed object model to which it belongs is associated with a persistent store
coordinator), it must not (indeed cannot) be changed. This is enforced at runtime: any
attempt to mutate a model or any of its sub-objects after the model is associated with a
persistent store coordinator causes an exception to be thrown. If you need to modify a
model that is in use, create a copy, modify the copy, and then discard the objects with
the old model.
I've never tried to modify one at runtime, so I'm not sure exactly how well this works when you have an existing SQLite persistence store, if at all. But it's probably worth playing around with NSEntityDescription to see if it gets you close to what you are trying to do.
You typically create the managed object model graphically using Xcode's Data Model Design tool. (If you wish you can construct the model programmatically at runtime
Core Data programming Guide
You can however:
Create a Object Model Context (outside of the current one you are in/using)
Create one or more Entities
Create a SEPARATE persistent store for that model
Save entities etc...
Close the store when you're done
You can't change models on the fly as they are pretty much fixed when they're pulled into the runtime environment.
This is a two part question, here is the situation:
I have an app that lists a set of product models. The user should be able to select from this list the product models that they specifically own. They can own more than 1 of the same type of product and should also be able to set a custom name for the products they own. So I set up my data model with two entities. Product, and OwnedProduct. OwnedProduct inherits from the Product entity and adds a customName property.
Question 1: Is this the best way to implement the model or should I be doing something with relationships? Right now I don't have any relationships in place.
The next question involves actually creating an OwnedProduct record from one of the Products that has been selected by the user.
Question 2: Is there a way to take the selected Product object, duplicate it , and then cast it as an OwnedProduct? Or would I have to create a brand new instance of OwnedProduct and then manually assign all of it's properties from the properties of the Product instance?
Question 1: Is this the best way to implement the model or should I be doing something with relationships? Right now I don't have any relationships in place.
Do you plan to have multiple owners within the same context?
Can a single product be owned by different owners with different custom names?
If yes I would take a look at relationships. I would not duplicate a product because of an ownership. If the product changes, it probably should change for all owners.
A possible datamodel for your requirements:
Question 2: Is there a way to take the selected Product object, duplicate it , and then cast it as an OwnedProduct? Or would I have to create a brand new instance of OwnedProduct and then manually assign all of it's properties from the properties of the Product instance?
As the clone will be a separate instance within your context you have to create a new one and copy all necessary properties. You can speed things up by iterating over NSEntityDescription properties and relationships. There is already a solution to cloning NSManagedObjects on SO
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.