fetchedresultscontroller with two entities - predicate to target each entity? - iphone

My iPhone app has a summary page (UITableView) where I would like to show a quick overview and therefore I need to get info from several entities. It was suggested to create an abstract parent entity and have my two entities as children of this one. This do allow me to fetch the two entities using the one fetchedresultscontroller.
This works but I find that I need to filter the return a small bit. Because of the 'hack' above these entities have nothing in common so I need completely separate predicates.so from EntityA I would need "color = blue" and from EntityB "length >= 10". Because the entity I'm actually querying have none of these this doesn't work at all.
Is there a way to do this or what's the best approach here?

Niether the UITableView or the NSFetchedResultsController is designed to deal with more than one entity at a time. Moreover, it seldom makes any sense to try to do so. If you find yourself in such a situation, you probably need to rethink your data model design.
If entities are logically associated with each other then they should be linked by a relationship. If data from any two objects is to be displayed in the same tableviewCell without being gibberish then they must have some logical association and therefore should be linked by a relationship of some kind. To display in the table, you fetch one side of the relationship and then walk the relationship/s to find the other related objects.
If the logical association is strong, it should be defined as a formal relationship in the data model e.g.:
EntityA{
//... some attributes
b<-->B.a
}
EntityB{
//...some attributes
a<-->A.b
}
However, if the relationship is weak or transient, then you should use a fetched property to relate them. The fetched property dynamically searches for other entities based on a preprogrammed fetch.
EntityA{
creationDate:date
someBs--(creationDate=$FETCH_SOURCE.creationDate)-->B
}
EntityB{
creationDate:date
}
A key concept here is that Core Data is providing the entire model layer of your Model-View-Controller design. It is not just a dumb database but an active object graph that models both the data itself and its behavior. Once you have a properly designed data model, problems with the controllers and views resolve themselves automatically.

If i understand correctly, you can use notifications and send a dictionary of required information to the UITableView view controller class.

Related

Core Data entity inheritance --> limitations?

I thought I'll post this to the community. I am using coredata, and have two entities. Both entities have a hierarchical relationship. I am noticing quite a lot of duplicated functionality now, and am wondering if I should re-structure to have a base Entity which is abstract (HierarchicalObject), and make my entities inherit from them.
So the question is are there some limitations of this inheritance that I should take into account? Reading some of the posts out there, I see a few trade-offs, let me know if my assumptions are correct.
(Good) clean up structure, keep the HierarchicalObject functionality in one spot.
(Ok) With inheritance, both objects now end up in the same sqlite table (I am using Sqlite as the backend). So if the number of objects grow, search/sorting could take longer? Not sure if this is a huge deal, as the number of objects in my case should stay pretty static.
(not so good) With inheritance, the relationship could get more complicated? (http://www.cocoadev.com/index.pl?CoreDataInheritanceIssues)
Are there other things to take into account?
Thanks for your comments.
I think it's a mistake to draw to close a parallel between entities and classes. While very similar they do have some important differences.
The most important difference is that entities don't have code like a class would so when you have entities with duplicate attributes, your not adding a lot of extra coding and potential for introducing bugs.
A lot of people believe that class inheritance must parallel entity inheritance. It does not. As a long as a class descends from NSManagedObject and responds to the right key-value messages for the entity it represents, the class can have many merry adventures in it's inheritance that are not reflected in the entities inheritance. E.g. It's fairly common to create a custom base class right below NSManagedObject and the have all the subsequent managed object subclasses inherit from that regardless of their entities.
I think the only time that entity inheritance is absolutely required is when you need different entities to show up in the same relationship. E.g:
Owner{
vehical<-->Vehical.owner
}
Vehical(abstract){
owner<-->Owner.vehical
}
Motocycle:Vehical{
}
Car:Vehical{
}
Now the Owner.vehical can hold either a Motocycle object or a Car object. Note that the managed object class inheritance for Motocycle and Car don't have to be same. You could have something like Motocycle:TwoWheeled:NSManagedObject and Car:FourWheeled:NSManagedObject and everything would work fine.
In the end, entities are just instructions to context to tell it how the object graph fits together. As long as your entity arrangement makes that happen, you have a lot flexibility in the design details, quite a bit more than you would have in an analogous situation with classes.
I thought it would be useful to mention that the Notes app on iOS 10 uses inheritance in its Core Data model. They use a base entity SyncingObject, that has 7 sub-entities including Note and Folder. And as you mentioned all of these are stored in the same SQLite table which has a whopping 106 columns, and since are shared among all entities most are NULL. They also implemented the folder-notes one-to-many relation as a many-to-many which creates a pivot table, which might be a work-around for an inheritance problem.
There are a couple of advantages to using entity inheritance that likely outweigh these storage limitations. For example, a unique constraint can be unique across entities. And a fetch request for a parent entity can return multiple child entities making UI that uses fetched results controller simpler, e.g. grouping by accounts or folders in a sidebar. Notes uses this to show an "All Notes" row above the Folder rows which is actually backed by an Account.
I have had issues in the past with data migration of models that had inheritance - you may want to experiment with that and see if you can get it to work.
As you noted also, all objects go in one table.
However, as Core Data is managing an object graph, it is really nice to keep the structure the way you would naturally have it just modeling objects - which includes inheritance. There's a lot to be said for keeping the model sane so that you have to do less work in maintaining code.
I have personally used a fairly complex CD model with inheritance in one of my own apps, and it has worked out OK (apart from as I said having issues with data migration, but that has been so flakey for me in general I do not rely on that working any longer).

Entity Framework Service Layer Update POCO

I am using the Service Layer --> Repository --> Entity Framework (Code-First) w/POCO objects approach, and I am having a hard time with updating entities.
I am using AutoMapper to map my Domain Objects to my View Models and that works good for getting the data, no how do I get that changes back into the database?
Using pure POCO objects, I would assume that there is no sort of change tracking, so I see my only option is to handle it myself. Do you just make sure that your View Models have the EXACT same properties as your Domain Objects? What if I just change a field or two on the View Model? Won't the rest of the fields on the Domain Object get overwritten in the database with default values?
With that said, what is the best approach?
Thanks!
Edit
So what I am stumbling on is this, lets take for example a simple Customer:
1) The Controller has a service, CustomerService, that calls the services GetCustmoerByID method.
2) The Service calls into the CustomerRepository and retrieves the Customer object.
3) Controller uses AutoMapper to map the Customer to the ViewModel.
4) Controller hands the model to the View. Everything is great!
Now in the view you do some modifications of the customer and post it back to the controller to persist the changes to the database.
I would assume at this point the object is detached. So should the model have the EXACT same properties as the Customer object? And do you have to make hidden fields for each item that you do not want to show, so they can persist back?
How do you handle saving the object back to the database? What happens if your view/model only deals with a couple of the fields on the object?
If you're using EF Code First, i.e: the DbContext API, then you still do have change tracking which is taken care of by your context class.
after making changes to your objects, all you have to do is call SaveChanges() on your context and that will persist the changes to your database.
EDIT:
Since you are creating a "copy" of the entity using AutoMapper, then it's no longer attached to your context.
I guess what you could do is something similar to what you would in ASP.NET MVC (with UpdateModel). You can get the original entity from your context, take your ViewModel (which may contain changed properties) and update the old entity, either manually (just modified properties), or using AutoMapper. And then persist the changes using context.SaveChanges().
Another solution would be to send the model entity as [part of] the ViewModel. This way, you'll have your entity attached to the container and change tracking will still work.
Hope this helps :)
You are absolutely right that with a detached object you are responsible for informing the context about changes in your detached entity.
The basic approach is just set the entity as modified. This works for scalar and complex properties but it doesn't work for navigation properties (except FK relations) - for further reading about problems with navigation properties check this answer (it is related to EFv4 and ObjectContext API but same problems are with DbContext API). The disadvantage of this approach is that all fields in DB will be modified. If you just want to modify single field you still have to correctly fill others or your database record will be corrupted.
There is a way to explicitly define which fields have changed. You will set the modified state per property instead of whole entity. It is little bit harder to solve this on generic approach but I tried to show some way for EFv4 and for EFv4.1.
I agree with #AbdouMoumen that it's much simpler to use the model entities at the view level. The service layer should provide an API to persist those entities in the data store (db). The service layer shouldn't dumbly duplicate the repository lawyer (ie: Save(entity) for every entity) but rather provide a high level save for an aggregate of entities. For instance, you could have a Save(order) in the service layer which results in updating more basic entities like inventory, customer, account.

Core Data - save existing managed object and show it in an another view

I'm working on an table drill-down style iPhone app that has prepopulated data. I use Core Data and NSFetchedResultsController to populate the table views. In the last level of the table view which shows an item (managed object) I want my user to be able to select that item which should eventualy be shown in another view. That other view would be a kind of a favorite list (implemented in a tab view). The user would then have a choice of deleting or adding other items to the favorite list.
My model has three entities each representing one level of table view. Higher level entity has a to-many relationship to lower level entity and inverse relationships are to-one
How do I use the existing managed object (object in the last level of table view) to save it and show it in favorite list view? Should I create new entity and establish relationship between the two?
My model has three entities each
representing one level of table view.
That is thinking backwards. What you have is three entities that exist logically in a hierarchy and the hierarchy of views reflects that logical structure. The views exist to display the data, the data does not exist to display the views. It's an important concept to grasp and if you fail to do so, your application design will always be overly complex, fragile and hard to extend and maintain. The data model always comes first and the logical relationships within the data model itself and the users interactions with that data ultimately control the UI structure of the app.
It's an easy trap to fall into because the instructional materials always start with the interface first. However, in real app design, you start with the data model first and work forward to the interface.
In this case, if you want to store favorites of some entity you have two choices. If the entity being a favorite is part of the core relationship between data and the user and you only have one set of favorites, then you could legitimately add a boolean "isFavorite" attribute to the entity and then just fetch al the entities where "isFavorite==YES"; If you have multiple list of favorites then the best method would to to create a FavoritesList entity and then relate each favorites entity to the objects it is supposed to list.
If the favorites are a minor and peripheral part of the user's interaction with the data you could store the objectIDs in the user defaults.
Yes, you could create a new entity and store the relationship. It's not necessarily the only way to do it -- you could store pointers to your NSManagedObjects in a container like an NSMutableArray -- but if you want to remember that list for later (i.e. save it between launches), it might make the most sense to also store it using Core Data.

RIA services presentation model with 1-many or many-many relationships

I'm trying to get a presentation model (discussed here and here) working in RIA. All the examples I can find are simple, flat data entities with no 1-many or many-many relationships, which are what I can't get working - specifically, on updates and inserts into associative relationships.
Queries I can get working fine - I have my presentation classes marked up with Association attributes (and Include attributes, where appropriate), and I have a good understanding about how data is loaded into the client side and maintained there as entities. I also have inserts of new entities covered. However, I'm experiencing the following problems. For the following examples, assume we have simple Album and Artist entities, where an Album has a single artist and an Artist can have zero to many albums. Both have a Name property.
On the client side, if I do myArtist.Albums.Add(anAlbum) or myArtist.Albums.Remove(anAlbum), nothing happens. HasChanges returns false. (Note that myArtist and anAlbum were obtained solely in code by loading the entities and iterating to get references to specific entities: I'm not doing anything in UI or with DomainDataSources yet, just dinking around).
If I update the Name on an Artist and SubmitChanges, when the Update method gets called on the server, the Albums collection is null.
Does anyone have any suggestions, or can you point me to an example that uses more complex objects?
EDIT (keeping the above for posterity): Alright, it appears that the second issue (a reference to an entity or a collection of entities showing as null when Update gets called on the server) exists because the child entites aren't marked as Changed and so they aren't being serialized and sent back. I know you can force that to happen by using [Composition] and I have gotten it to work that way, but this is not a compositional relationship and I want both entities to be "top-level" entities. How can I mark an entity as changed?
The problem was that my [Association] attributes weren't correctly defined. I didn't realize that the association's Name property has to be the same on both sides of the association. When the names are the same and you do a build, the generated code on the client uses a different constructor for the EntityCollection used by the "parent" to refer to the "children" than it does if the associations aren't set up right. The new constructor takes callbacks that do a little bit of extra handling when you call Add and Remove on the collection - specifically, they take the child entity you are adding or removing and modify the property on it that refers to its parent so that everything remains in sync: the collection you removed the object from, the collection you added it to, and the object's reference to its parent.

Casting Entity Framework Entities in the "Wrong" Direction

I am using the Entity Framework and have an inheritance structure with a base Entity (let's call it Customer) and a derived Entity, let's call it AccountCustomer. The difference is that an AccountCustomer has extra details (such as payment terms etc.) stored in a separate table in the database and therefore extra properties in the Entity.
I want to allow users to 'promote' a specific Customer to be an AccountCustomer. I need to keep the same primary key (a composite key visible to users and used as the customer reference).
At the moment my feeling is that calling a stored procedure to create the additional record in the Accounts table is the only way to go, but up to now we have not bypassed the Entity Framework so would prefer to avoid this technique if possible.
Has anybody any Entity Framework focussed solutions?
This is one of those "Please don't do this" scenarios.
You are thinking about this strictly in terms of tables, instead of in object-oriented terms.
A particular customer is a particular customer. The kind of thing he is never changes. Now, his Status may change, or he may acquire additional AccountProperties, but he never transitions from being one kind of thing (Customer) to another kind of thing (AccountCustomer). It simply doesn't make sense conceptually (a generic fruit doesn't morph into an apple, does it? no! it starts as an apple with one status, and ends up as an apple with a new status), and it certainly is impossible in .NET object-oriented programming ... which would make it impossible in an ORM like EF.
So please think about a sensible way to conceptualize this, which will lead to a sensible way to express this in object-oriented terms, which will lead to a sensible EF solution.
I have solved this by a work-around.
Load all the related navigation properties of the base class, including itself
var customer = db.Customers.Include("whatever dependince you have").FirstOrDefault(u=>u.UserId == userId);
//you can repeat this for all of your includes
Cache the navigation properties to local variables i.e. var profile = customer.Profile;
Delete the base class by db.Customer.Remove(customer);
Create the derrived class var accountCustomer = new AccountCustomer();
Set all of its properties and navigation properties from the base class i.e.
accountCustomer.UserId = customer.UserId;
accountCustomer.Profile = profile; // do the same for all of the properties and navigation properties from the base class
Add the new class back to the db
this.Entry<T>(accountCustomer).State = EntityState.Added;
Call db.SaveChanges()
That's it!