CoreData SQLite - Data looks deleted but in fact, it is not - cocoa

The app allows to manage a list of Suppliers and a list of Products available from those Suppliers. Data model contains 2 entities: Supplier and Product.
Supplier has a 1-to-many relation to Product, with delete rule set to Cascade (as I don't want to keep records of a supplier's products if it gets put out of business). Product has default relationship settings.
In IB, I have 2 array controllers. One points to the Supplier entity, with Parameters: MOC bound to AppDelegate and MKP=managedObjectContext. The other points to the Product entity, with Parameters: MOC bound to AppDelegate and MKP=managedObjectContext, and with Controller Content: Content Set bound to Suppliers array controller, CK=selection and MKP=name_of_relation.
On the interface I have 2 NSTableViews for Suppliers and Products, and buttons to Add/Remove from the tables. When I select a Supplier, only its specific Products are displayed on the Products table. When I delete a product, the product disappears from the table. It works as intended.
I thought it was working fine, until the day where I was curious to see how CoreData actually manages the data fields and tables inside the SQLite database. So I opened it using the SQLiteManager add-on in Firefox and... horror! I see that the Products are not deleted. The data are still there! Only the reference to the Supplier was deleted and that's why it doesn't appear anymore in the table, leading me to think that it had been correctly deleted.
What did I do wrong? Is it something with the Content Set bindings?
Thanks for advice.

I just ran a test on this and the result was that the relationship entities where completely deleted from the sqlite database. I think you need to check your cascading settings again exactly in IB. Did you make sure you have a save: statement?

Related

Binding posted values to view model using default binder - MVC3

Can the Model Binder in MVC bind posted values to a view-model object containing hierarchy?
I have a Customer, Order and OrderItem tables. OrderItem.OrderID points to Order.ID; and Order.CustomerID points to Customer.ID i.e. the common Customer -> Order -> OrderItem setup.
And I have a view model – Customer which contains Order objects and then OrderItem objects as well.
I have created the EF model objects using the designer tools in VS. (created database tables first in SQL, then created the classes automatically using the EF tools)
On a single page (view), let's say, I will allow the user to create a new Customer record, an Order, and some OrderItem(s).
When the user fills the form (creates a new Customer, Order and OrderItems on this one view), clicks on the submit button; will the default binder move all the values from the posted values to my view model? (the view model class carries properties for Customer, Order, OrderItem in a hierarchy i.e. Order is a property within Customer and OrderItem is a property within Order). Is EF smart enough to map posted values to such an object?
Yes, MVC is smart enough to handle this binding. It is fairly common in MVC to build up a 'complex' View Model made of several properties which are themselves Models. Binding to collections and dictionaries is harder, but entirely possible.
In EF, you can easily define relationships between objects (e.g. there is a 1 to many relationship between Customer and Order), and EF will handle this just fine. The code for the 'Create customer with order and order items' will (I imagine) be fairly straightforward but I'm not an EF expert, though - so I will have to leave detailed answers to someone else.
However, the EF code for an 'Edit Customer and/or Order and/or Items' screen would actually be quite complicated - and so you'd probably be better splitting these off into separate actions, as this would simplify the code quite a lot.

How do I create a UI for a Many-to-Many relationship?

Can anyone advise on the best way to create a UI for establishing Many-to-Many relationships ?
Lets use an example from a previous question List <<-->> Patient.
I can create two separate Table Views, one for Lists and another for Patients which will allow the user to create Lists and Patients using two separately created Array Controllers (Lists and Patients), one linked to the List entity and other linked to the Patient entity.
Now I would like to be able to add/remove Patients from a List by creating an Table View that shows only Patients in the selected List. To do this I create a Array Controller (ListPatients) linked to the entity Patient with a Content Set binding to Lists.selection.patients.
Now things stop working nicely from here on....
If I bind a button to the ListPatients.add method then a NEW Patient gets created - there seems to be no way to simply add a NEW relationship between an existing Patient and the List.
Ideally what I would like to be able to do is to have a drop down list to select the Patient from.
Does anyone have any suggestions as to how best to do this without needing to create a new entity to represent this relationship.
What you need is a swapping Master-Detail view where either the List table or the Patient table is the Master or the Detail at any particular time.
When the List is the Master view, selecting a row will cause the Detail view to display all the Patient objects in the rowList.patients relationship. When the Patient is the Master view, selecting a row will cause the Detail view to display all the List objects in the rowPatient.lists relationship.
You really do want to break up the UI so the users always have a clear idea what the relationship is between the two tables. I would recommend a set of four tables, two each for each Master-Detail setup. That way, the user will also understand what they are looking at.
That will also make it easy to add new objects. Just put an add new button under the detail table and the user will understand that clicking it will add a new object to the relationship of the object selected in the Master view.

Making entity framework treat views with many-to-many relationships, like it does tables with many-to-many relationships

I have three views that I've manually created in the DB.
First view is "Region", the second is "FIPS" and the last is a many-to-many between them called "Region2FIPS". These are all views, and I only need read access the data, so I'm not worried about having updateable views.
I have added each of these views to Entity Framework, and created the appropriate associations between them.
Region to Region2FIPS is a 1 to many.
FIPS to Region2FIPS is a 1 to many.
The "Region2FIPS" view contains only two columns, one called "FIPSID" the other "RegionID". These column are associated with their respective views in the relationships I defined above.
When this type of association is made on tables in the DB, Entity Framework knows that it is a many-to-many relationship and it creates a navigation property on "Region" called "FIPS" that I can use to navigate through the child collection of FIPS. It does likewise for "FIPS" to "Region".
However, when done manually, with views, it does not exhibit that behavior. Instead, my "Region" object has a collection of "Region2FIPS" objects, which each have a navigation property called "FIPS" which is of type "FIPS". And my "FIPS" object has a collection of "Region2FIPS" objects, which each have a navigation property called "Regions" of type "Region".
I assume this has something to do with the fact that I can't create foreign key references on the views, so entity framework doesn't realize the many-to-many relationship. But I thought that if I manually created the many-to-many relationship between the views it would recognize it and properly handle the navigation between the types. Is there a way for me to force it to do this?
It's possible, but the designer doesn't really help you here. You have to do the mapping manually.
One fairly easy way is to use Code First mapping. But this means your model has to be Code First to begin with. If you're writing a new model, just do that.
If you're using DB First mapping, however, you will have to do the mapping manually. Your SSDL will probably already be correct, once you define the "primary keys" of the views. You would then have to remove the "Region2FIPS" objects from the CSDL (not just from the designer!) and manually patch up the MSL.
Perhaps the easiest way to do this would be to use the designer to automatically map real DB tables (not views) with a similar schema and then replace the table names with view names in the EDMX, using the XML editor.

displaying balance in core data

I have 3 entities in an example app:
Account
name
balance (NSDecimalNumber overall balance of account)
balances (to-many relationship with Balances)
transactions (many-to-many relationship with Transaction.accounts)
Transaction
payee
amount
accounts (many-to-many relationship with Account.transactions)
balances (many-to-one relationship with Balances.transaction)
Balance
amount
account (one-to-many relationship with Account.balances)
transaction (one-to-many relationship with Transaction.balances)
I want to display the transactions of a particular account in an NSTableView. The problem comes in when I want to display the balance of the current account. Because a transaction may be associated with multiple accounts, it may have multiple balances. I can't think of a way to select the particular balance associated with the current account being displayed in an NSTableColumn. Does anyone have any suggestions of how to change the model or how to connect things up to the NSTableView in such a way that the proper balance is displayed?
The only thing I can think of is to create a sub-class of NSCell that knows how to select the balance associated with the current account view or an NSValueTransformer that does a similar thing. This seems like a very inelegant solution though. If there is a better way I would like to know how.
Update
Here's a screenshot of a demo app that illustrates the above. I would like the far right column to display the balance as of that specific transaction. Works well enough if the transaction has a balance attribute; however, in my app the balance is stored in a separate table because there may be multiple types of balances for each transaction. I can't figure out how to get it to display the proper balance in the table view though:
Have you considered populating the table via this NSTableViewDataSource method:
- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
I know, it looks ugly, but you can do somersaults with it.
Bind the table column's value binding to your array controller of Accounts with the controller key selection and the model key path balance.

How do I delete an entity when removing it from an array controller?

I have an entity (e.g. Employee) in a managed object model that is related to two other entities (e.g. Department and Team). Both relationships are one-to-many (i.e. an Employee must have one Department and one Team, Teams and Departments have many Employees). The two may or may not overlap (e.g. a team might be made up of employees from HR, Accounting & I.T. or it might jut consist of several employees from the one department).
Department <-->> Employee <<--> Team
I have two NSArrayControllers providing data for two NSTableViews, a Department table and a Team table. Employees can move between departments and between teams without any problems but I'm not sure how to delete (fire) the employee.
If I send either of the array controllers a remove message the employee is taken out of the team (for example) but left in the department and the object graph is in an inconsistent state. Even if I call the remove action on both controllers the object is not deleted - it is orphaned and just hangs around in limbo.
Originally I had the Department & Team relationships (of the Employee entity) set to a delete rule of Nullify but even changing one or both to cascade doesn't help.
Do I need to override the remove: action on the array controllers to actually delete the employee or am I missing something really obvious?
The NSArrayController has two different behaviors when you're using Core Data. If it is configured to simply fetch objects directly from the managed object context, it will delete the objects when they are removed.
If you're binding the contentSet to another controller, like it sounds like you are in this case, the default behavior is to simply remove the object from the relationship. If you want to delete it, though, there is a "deletes object on remove" binding option, which will produce the result you want.

Resources