I've got a data model where there is a Person entity, which has a transformable attribute which is an array of dictionaries containing information. The model is much bigger than that, this is just the part I'm having trouble with. It was designed this way by an old developer, and in taking over the project I need to migrate this to be 100% core data.
So what I need to do is create a new entity, then step through each dictionary in the Person's array and create new instances of that entity with the information from that dictionary. I thought I could use an NSEntityMigrationPolicy to set up a custom migration for this new Entity, but it seems the Core Data migration is expecting X number of source entities to translate to X number of destination entities. Because I technically have 0 source entities right now (because they're in an array that Core Data doesn't really know anything about), I'm not sure how I can make the migration create new entities during the process.
What, or rather where in the migration procedure, is the best way to do what I'm trying to accomplish? I've always used lightweight migration in the past, so this is my first adventure in custom migration.
It would help to have a sense of your data model (schema) - but let's assume that your Person entity now holds home address and list of favorite restaurants. And let's further assume that you will be creating new entities Address and Restaurant along with the following relationships:
Person has one Address, so there's a to-one relationship from Person to Address called "homeAddress". There's an inverse to-many relationship from Address to Person, because many people could live at the same address.
Person has a to-many relationship (called restaurants) to Restaurants. Restaurant could also has a to-many relationship to Person (though this might be one of those cases where bidirectionality doesn't really make sense).
Anyway, the point is that now - in addition to your PersonToPerson NSEntityMigrationPolicy subclass, you will also have PersonToAddress and PersonToRestaurant. These will be the places that you unpack the old data and use it to instantiate and initialize new Address and Restaurant objects.
Of course, there are lots of other complicating issues. For example, you won't want to be creating a new instance of the same Restaurant for every Person who likes it. You will need to keep track of newly created Restaurants.
You will want to order your mappings strategically - probably with PersonToPerson first.
You might want to look at Marcus Zarra's Core Data sample code and maybe even buy his book.
Related
How do you solve a situation when you have multiple representations of same object, depending on a view?
For example, lets say you have a book store. Within a book store, you have 2 main representations of Books:
In Lists (search results, browse by category, author, etc...): This is a compact representation that might have some aggregates like for example NumberOfAuthors and NumberOfRwviews. Each Author and Review are entities themselves saved in db.
DetailsView: here you wouldn't have aggregates but real values for each Author, as Book has a property AuthorsList.
Case 2 is clear, you get all from DB and show it. But how to solve case 1. if you want to reduce number of connections and payload to/from DB? So, if you don't want to get all actual Authors and Reviews from DB but just 2 ints for count for each of them.
Full normalized solution would be 2, but 1 seems to require either some denormalization or create 2 different entities: BookDetails and BookCompact within Business Layer.
Important: I am not talking about View DTOs, but actually getting data from DB which doesn't fit into Business Layer Book class.
For me it sounds like multiple Query Models (QM).
I used DDD with CQRS/ES style, so aggregate roots are producing events based on commands being passed in. To those events multiple QMs are subscribed. So I create multiple "views" based on requirements.
The ES (event-sourcing) has huge power - I can introduce another QMs later by replaying stored events.
Sounds like managing a lot of similar, or even duplicate data, but it has sense for me.
QMs can and are optimized to contain just enough data/structure/indexes for given purpose. This is the way out of "shared data model". I see the huge evil in "RDMS" one for all approach. You will always get lost in complexity of managing shared model - like you do.
I had a very good result with the following design:
domain package contains #Entity classes which contain all necessary data which are stored in database
dto package which contains view/views of entity which will be returned from service
Dto should have constructor which takes entity as parameter. To copy data easier you can use BeanUtils.copyProperties(domainClass, dtoClass);
By doing this you are sharing only minimal amount of information and it is returned in object which does not have any functionality.
I´m a little confused about inheritance and relationships in core data, and I was hopping someone could drive to the right path. In my app i have created 3 entities, and none of them have (and are not suppose to have) common properties, but there´s gonna be a save and a load button for all the work that the user does. From my understanding I need to "wrap" all the entities "work" into an object which will be used to save and load, and my question is, do I need to create relationships between the entities? Because I have to relate them somehow and this is what make sense to me. Is my logic correct?
I'm implementing a budget calculator, and for the purpose of everyone understand what my issue is, I´m going to give an practical example and please correct me if my logic is incorrect:
Let´s just say you are a fruit seller, and because of that it´s normal to have a database of clients and also a fruit database with the kinds of fruit you sell. From my understanding I find two entities here:
Client with properties named: name, address, phone, email, etc.
Stock with properties named: name, weight, stock, cost, supplier, etc.
TheBudget with properties named: name, amount, type, cost, delivery, etc.
I didn´t put all the properties because I think you get the point. I mean as you can see, there´s only two properties I could inherit; the rest is different. So, if I was doing a budget for a client, I can have as many clients I want and also the amount of stock, but what about the actual budget?
I´m sorry if my explanation was not very clear, but if it was..what kind of relationships should I be creating? I think Client and TheBudget have a connection. What do you advise me?
That's not entirely correct, but some parts are on the right track. I've broken your question down into three parts: relationships, inheritance and the Managed Object Context to hopefully help you understand each part separately:
Relationships
Relationships are usually used to indicate that one entity can 'belong' to another (i.e. an employee can belong to a company). You can setup multiple one-to-many relationships (i.e. an employee belongs to a company and a boss) and you can setup the inverse relationships (which is better described with the word 'owns' or 'has', such as 'one company has many employees).
There are many even more complicated relationships depending on your needs and a whole set of delete rules that you can tell the system to follow when an entity in a relationship is deleted. When first starting out I found it easiest to stick with one-to-one and one-to-many relationships like I've described above.
Inheritance
Inheritance is best described as a sort of base template that is used for other, more specific entities. You are correct in stating that you could use inheritance as a sort of protocol to define some basic attributes that are common across a number of entities. A good example of this would be having a base class 'Employee' with attributes 'name', 'address' and 'start date'. You could then create other entities that inherit from this Employee entity, such as 'Marketing Rep', 'HR', 'Sales Rep', etc. which all have the common attributes 'name', 'address' and 'start date' without creating those attributes on each individual entity. Then, if you wanted to update your model and add, delete or modify a common attribute, you could do so on the parent entity and all of its children will inherit those changes automatically.
Managed Object Context (i.e. saving)
Now, onto the other part of your question/statement: wrapping all of your entities into an object which will be used to save and load. You do not need to create this object, core data uses the NSManagedObjectContext (MOC for short) specifically for this purpose. The MOC is tasked with keeping track of objects you create, delete and modify. In order to save your changes, you simply call the save: method on your MOC.
If you post your entities and what they do, I might be able to help make suggestions on ways to set it up in core data. You want to do your best to setup as robust a core data model as you can during the initial development process. The OS needs to be able to 'upgrade' the backing store to incorporate any changes you've made between your core data model revisions. If you do a poor job of setting up your core data model initially and release your code that way, it can be very difficult to try and make a complicated model update when the app is in the wild (as you've probably guessed, this is advice born out of painful experience :)
From what I learned in school many years ago, an entity is an actual object in a database. A recordset or a dataset.
This is how I remember it but I may be wrong.
But in many books I read an entity is not an object but the data model, like a class, for the object. When I am in the Core Data - Data Model Editor in Xcode and I click on "Add Entity" I don't add an object to the database but another data model.
So I am confused!
An entity, is it like an object, or like a class I can create objects from?
If you want to become proficient in core data you should learn the associated vocabulary which admittedly might be counter-intuitive at first.
Let me stress that core data is not just a database wrapper but an object graph. Therefore, please take the equivalencies I give here with a grain of salt.
An entity would correspond to a table in a database.
An attribute would correspond to the particular fields in a table.
A relationship (to-one or to-many) would be the presence of a foreign key.
A many-to-many relationship would be a join table with two foreign keys.
One "record" in a database would be an instance of a certain entity.
Note that it is common practice to model entities with corresponding classes which are subclasses of NSManagedObject. Thus instantiation works pretty much like with any other object, only that they are persisted in the database store.
Definitely spend some time on the Core Data Programming Guide.
Core data is not a database and so I am getting confused as to how to create, manage or even implement Lookup tables in core data.
Here is a specific example that relates to my project.
Staff (1) -> (Many) Talents (1)
The talents table consists of:
TalentSkillName (String)
TalentSkillLevel (int)
But I do not want to keep entering the TalentSkillName, so I want to put this information into another, separate table/entity.
But as Core Data is not really a database, I'm getting confused as to what the relationships should look like, or even if Lookup tables should even be stored in core data.
One solution I'm thinking of is to use a PLIST of all the TalentSkillNames and then in the Talents entity simply have a numeric value which points to the PLIST version.
Thanks.
I've added a diagram which I believe is what you're meant to do, but I am unsure if this is correct.
I'd suggest that you have a third entity, Skill. This can have a one to many relationship with Talent, which then just has the level as an attribute.
Effectively, this means you are modelling a many-to-many relationship between Staff and Talent through the Skill entity. Logically, that seems to fit with the situation you're describing.
This is only an example.
Say that you have 2 entities for 2 different context boundaries. The first context is the SkillContexter, the entity is 'Player' and has 3 properties: Id, Name and SkillLevel. In the other context (Contactcontext) the entity is 'Player' and has 3 properties: Id, Name and EMail.
How do I persist these entities to the database? I only want one table (Player) and not two tables (PlayerContact, PlayerSkill). Shall I have two different repositories for player that save the different context-entities, but into same table? Or shall I have a "master" player entity that holds all properties that I need to save, so that I create a new entity called PlayerMaster that has 4 properties: Id, Name, EMail and SkillLevel?
The first solution gives me more repositories, and the second makes me make a "technical" entity that only purpose is to save data to a database, and that feels really wrong, or is there a better solution that I have missed?
How have you guys solved it?
When I first started with DDD, I also wrestled with the Context + Domain + Module + Model organization of things as well.
DDD is really meant to be a guide to building your domain models. Once I stopped trying to sub-organize my Contexts and boundies, and started thinking of what really is shared between entities - things started to fit together better.
I actually do not use contexts, unless it is a completely different application (app = context). Just my preference. But, I do have Modules that only share base abstracts and interfaces common throughout code (IRepository, IComponent, etc). The catch is, DDD says that Modules can share entities between modules - but, only on a very limited scale (you really don't want to do it often).
With that in mind, I would get away from using contexts and move to a "what really am I trying to accomplish, what do these models have in common). Here's what I would think, reading your question (if I understand them).
Person() is a base entity. It has ID and Name.
PlayerSkill() is a Value Object, that is
accessable from Person().PlayerSkill.
Contact() is an entity that inherits Person(),
so it inherits ID and Name, and has additional Contact properties you want.
Now, I just tore up your domain. I know.
You can use a hybird approach as well:
Person() is a base entity. It has ID and Name.
Player() inherits Person(), applies Skill()
and other VOs.
Contact() inherits Person(), applies Address()
and other VOs.
I'm not quite sure what you mean by context boundaries, so my answer may be off.
Do the two Player entities represent the same physical entity (person)? If so, then I would create a single Player entity with all four attributes and store their data in a single table.