iphone SDK: Arbitrary tableview row reordering with core data - iphone

What is the best way to implement arbitrary row reordering in a tableview that uses core data? The approach that seems obvious to me is to add a rowOrder attribute of type Int16 to the entity that is being reordered in the tableview and manually iterate through the entity updating the rowOrder attributes of all the rows whenever the user finishes reordering.
That is an incredibly inelegant solution though. I'm hoping there is a better approach that doesn't require possibly hundreds of updates whenever the user reorders things.

If the ordering is something that the data model should modal and store, then the ordering should be part of the entity graph anyway.
A good, lightweight solution is to create an Order entity that has a one-to-one relationship to the actual entity being ordered. To make updating easy, create a linked-list like structure of the objects. Something like this:
Order{
order:int;
orderedObject<--(required,nullify)-->OrderObject.order
previous<--(optional,nullify)-->Order.next;
next<--(optional,nullify)-->Order.previous;
}
If you create a custom subclass, you can provide an insert method that inserts a new object in the chain and then sends a message down the next relationships and tells each object to increment its order by one then the message to its next. A delete method does the opposite. That makes the ordering integral to the model and nicely encapsulated. It's easy to make a base class for this so you can reuse it as needed.
The big advantage is that it only requires the small Order objects to be in alive in memory.
Edit:
Of course, you can extend this with another linked object to provide section information. Just relate that entity to the Order entity then provide the order number as the one in the section.

There is no better way and that is the accepted solution. Core Data does not have row ordering internally so you need to do it yourself. However it is really not a lot of code.

Related

Need some advice concerning MVVM + Lightweight objects + EF

We develop the back office application with quite large Db.
It's not reasonable to load everything from DB to memory so when model's proprties are requested we read from DB (via EF)
But many of our UIs are just simple lists of entities with some (!) properties presented to the user.
For example, we just want to show Id, Title and Name.
And later when user select the item and want to perform some actions the whole object is needed. Now we have list of items stored in memory.
Some properties contain large textst, images or other data.
EF works with entities and reading a bunch of large objects degrades performance notably.
As far as I understand, the problem can be solved by creating lightweight entities and using them in appropriate context.
First.
I'm afraid that each view will make us create new LightweightEntity and we eventually will end with bloated object context.
Second. As the Model wraps EF we need to provide methods for various entities.
Third. ViewModels communicate and pass entities to each other.
So I'm stuck with all these considerations and need good architectural design advice.
Any ideas?
For images an large textst you may consider table splitting, which is commonly used to split a table in a lightweight entity and a "heavy" entity.
But I think what you call lightweight "entities" are data transfer objects (DTO's). These are not supplied by the context (so it won't get bloated) but by projection from entities, which is done in a repository or service.
For projection you can use AutoMapper, especially its newer feature that I describe here. This allows you to reduce the number of methods you need to provide "for various entities" (DTO's), because the type to project to can be given in a generic type parameter.

classes and data presentation

I hope someone can give me some guidance in how to best approach this situation.
I am using dbcontext, wpf and sql server.
I am having situations were the presentation of the data requires other data than just what is coming from a single table. For example, if I had a person table but wanted to show also how many books they had read from related data, say fields would be name, address, NoOfBooks.
I currently create a new class, called say PersonBookPM, that I fill up with data from a linq query which combines the two tables which includes the above three fields.I create an observablecollection of that and make that the itemssource of the grid/listbox.
When I am then adding data to that I then need to use the selecteditem, convert that back to the single entity of person, and attach it back in to the context.
It seems like the classes have already been defined by the code gen and I am repeating the process only slightly differently.
Am I going round the houses here?
Thanks Scott

CoreData (IOS) Unique Constraint on Multiple columns?

Is it possible to, in CoreData for an iPhone app, have a Unique Constraint on Multiple columns?
For example:
have Event, EventItems, Items entities
the EventItems entity has a column ORDER
so the ORDER column for an EventItem should be unique for all it's instances relating to the same EVENT
So questions are:
How could I setup this constraint in coredata?
If it's not directly support any suggestions re how to put in place programmatically?
To do
For any core data constraint that operates on more then a single managed object at once you want to look at implementing:
- (BOOL)validateForDelete:(NSError **)error
- (BOOL)validateForInsert:(NSError **)error
- (BOOL)validateForUpdate:(NSError **)error
(I normally have core data make a .h and .m file for the entity, and then make my own category for things like this so I don't have as much work if I change the entity a little later)
If you have something that only needs to make sure values in a single managed object are correct you can use -validate<Key>:error:
To do what you are looking for I would make EventItems' validateForInsert/validateForUpdate
call a common method (maybe validateUniqueOrder). In that method I would use the relationship from EventItems to Event, and then fetch all the EventItems relating to the Event, and then check for uniqueness. I have fairly small sets of relations, so I didn't bother with anything fancy, but if you have a lot of event items associated with given events you might look into NSFetchRequests' setPropertiesToFetch method. Or maybe you can come up with a query that can directly search for duplicated values (I never could, so if you do, reply here to enlighten me).
How could I setup this constraint in coredata?
You control what goes into the data store, so you can impose any constraints you like, no matter how complex. But Core Data is not a database, and it doesn't implement the kinds of automatic constraints that you typically find in a RDBMS.
If it's not directly support any suggestions re how to put in place programmatically?
I'd do a check at the point in your code where you create or modify the affected object. In your case, you could create a custom setter for EventItem's 'order' property that compares the proposed 'order' to that of all the other EventItems related to the same event. Or, you might put the check in Event, and use an appropriate accessor to check any new EventItems as they're added.
Unique Constraints make sure that records in an Entity are unique by the given fields. But unique constraints along with To-Many relationship leads to a lot of weird issues while resolving conflicts.
e.g. “Dangling reference to an invalid object.”
This post is basically focused to a small problem that may take days to fix.
http://muhammadzahidimran.com/2016/12/08/coredata-unique-constraints-and-to-many-relationship/

I don't need/want a key!

I have some views that I want to use EF 4.1 to query. These are specific optimized views that will not have keys to speak of; there will be no deletions, updates, just good ol'e select.
But EF wants a key set on the model. Is there a way to tell EF to move on, there's nothing to worry about?
More Details
The main purpose of this is to query against a set of views that have been optimized by size, query parameters and joins. The underlying tables have their PKs, FKs and so on. It's indexed, statiscized (that a word?) and optimized.
I'd like to have a class like (this is a much smaller and simpler version of what I have...):
public MyObject //this is a view
{
Name{get;set}
Age{get;set;}
TotalPimples{get;set;}
}
and a repository, built off of EF 4.1 CF where I can just
public List<MyObject> GetPimply(int numberOfPimples)
{
return db.MyObjects.Where(d=> d.TotalPimples > numberOfPimples).ToList();
}
I could expose a key, but whats the real purpose of dislaying a 2 or 3 column natural key? That will never be used?
Current Solution
Seeming as their will be no EF CF solution, I have added a complex key to the model and I am exposing it in the model. While this goes "with the grain" on what one expects a "well designed" db model to look like, in this case, IMHO, it added nothing but more logic to the model builder, more bytes over the wire, and extra properties on a class. These will never be used.
There is no way. EF demands unique identification of the record - entity key. That doesn't mean that you must expose any additional column. You can mark all your current properties (or any subset) as a key - that is exactly how EDMX does it when you add database view to the model - it goes through columns and marks all non-nullable and non-computed columns as primary key.
You must be aware of one problem - EF internally uses identity map and entity key is unique identification in this map (each entity key can be associated only with single entity instance). It means that if you are not able to choose unique identification of the record and you load multiple records with the same identification (your defined key) they will all be represented by a single entity instance. Not sure if this can cause you any issues if you don't plan to modify these records.
EF is looking for a unique way to identify records. I am not sure if you can force it to go counter to its nature of desiring something unique about objects.
But, this is an answer to the "show me how to solve my problem the way I want to solve it" question and not actually tackling your core business requirement.
If this is a "I don't want to show the user the key", then don't bind it when you bind the data to your form (web or windows). If this is a "I need to share these items, but don't want to give them the keys" issue, then map or surrogate the objects into an external domain model. Adds a bit of weight to the solution, but allows you to still do the heavy lifting with a drag and drop surface (EF).
The question is what is the business requirement that is pushing you to create a bunch of objects without a unique identifier (key).
One way to do this would be not to use views at all.
Just add the tables to your EF model and let EF create the SQL that you are currently writing by hand.

Core Data: Inheritance, STI or otherwise?

I can't seem to find any information in the documentation or via Google on this, but if there is something, a pointer to it would be great.
In my app, I have a Thing as a core data class. I intend to have that Thing contain many Items which has a bunch of fields in it, like order and created_date and so forth. However, there are a variety of Item types, each with their own set of fields. Ideally, I'd like to create several subclasses of Item, so that I can access all the items together in a single array or something.
In Rails, I'd use STI for this. Does Core Data support similar behaviour?
Thanks!
You can create an Item abstract entity and then have each of your unique items extend from it. Keep the relationship in the abstract so that your Thing can see all of them.
Be warned, however, that under the hood, all of those children will actually be put into a single wide table so you will need to test for performance considerations.