I have a similar challenge to this post: Batch insert/update with entity framework from a couple years ago, I was hoping that the story may have changed since then.
In short, I am running a RESTful service, and as such I'd like a PUT to be document-oriented and take an object along with a collection of child elements in. The child elements have a unique string that I can use for determining existence.
Unlike the referenced poster, I don't have a query requirement; all I want to do is be able to take in a collection of my child elements and perform an insert on the child table for any that aren't already there, and an insert or delete on the many-to-many table to account for the current state of the collection. Ideally, with some efficiency. I realize that I might end up doing this as a sproc, I just wanted to see if there's an EF-native way that works first.
To do this you must either know which items are new or you must query DB first and merge your received items with loaded items. EF will not handle this for you. Also be aware that there are still no batch modifications. Each insert, update or delete is executed in separate roundtrip to database.
Related
I have EntityA which has a navigation property to EntityB. In the frontend it's possible to create a new EntityA and append it to EntityB. If I now try to save the new created EntityA, Breeze also want's to save the changes on EntityB (containing the new ID of the newly created EntityA). Is it somehow possible to avoid having EntityB, because in this specific use case it should be possible to append new entities to EntityB, but these should not be saved back (and also not be reported as pending changes)?
I see the possibility with using two EntityManagers, but this would mean that I can no longer have navigation properties between the two types.
Pascal is asking an important question: are Entity A and Entity B related one-to-one? More to the point are they related one-to-one such that A depends on B (i.e. A is a child of B)?
A typical relationship of this sort is the "extension" entity. Consider "Order" and "OrderExtension". "OrderExtension" is a bolt-on type with optional fields that "extend" the core order data. An order can have zero or one "OrderExtension" records.
Order is the parent in this example; it SHOULD NOT have a FK reference to the OrderExtension. The OrderExtension is the child and it SHOULD HAVE a required OrderID FK field. The parent Order can exist without a child, but the child OrderExtension cannot exist w/o the parent.
At least that's how I think it should be. I've often seen folks turn this around. They give the Order an OrderExtensionID FK field which is optional. The OrderExtension has no backpointer to the Order.
The weakness of this design is that it allows you to create multiple orphaned OrderExtension entities that don't belong to anything ... and you'll rarely know they are there.
I'm betting that's your situation. I'm betting that Entity B is like OrderExtension and Entity A is like Order. When you created the OrderExtension (B) and associated it with an Order (A), Breeze tried to maintain that relationship for you by updating the Order.OrderExtensionID property. That puts Order (A) in a modified state.
DO not proceed until you've figured this out. While Jeremy is correct that you can save one entity by cherry picking the pending changes - you can save B without saving A -, you risk breaking the integrity of your data!
From a modeling perspective you've made Entity A dependent on Entity B. If you don't save A at the same time you save B, there will be no way for someone using the database to know that the two are related.
Next time you query for either of them, neither you nor Breeze will know they are related. You will be unable to navigate between A and B. I'm pretty sure that's not what you had in mind.
You can pass an array containing the entities you wish to save to the saveChanges method to restrict which entities are saved.
From the breeze docs:
saveChanges ( [entities] [saveOptions] [callback] [errorCallback] ) async
Saves either a list of specified entities or all changed entities
within this EntityManager. If there are no changes to any of the
entities specified then there will be no server side call made but a
valid 'empty' saveResult will still be returned.
Parameters:
[entities] Array of Entity optional The list of entities to save.
Every entity in that list will be sent to the server, whether changed
or unchanged, as long as it is attached to this EntityManager. If this
parameter is omitted, null or empty (the usual case), every entity
with pending changes in this EntityManager will be saved.
I recently asked this question about how best to retrieve and display in a tableview the titles my FRC is using for section headers.
Following a line of research suggested by #Mike Pollard in the second answer to my question, I ran across this question and was immediately struck by the similarity to my situation, and by the 4th answer, posted by #aroth.
Aroth's approach certainly appears sound, and I've created a new Category entity. Specifically, Category has a to-many relationship with Item, and Item has a to-one relationship with Category. However I'm having trouble understanding one aspect implicit in his proposed solution, and, more fundamentally, in this relationship:
In my case, both Category(s) and Item(s)--"Item" is called "ListActivity" in my case, but "Item" will do for illustration purposes-- will be named via two corresponding user input fields, which seems like it could result in multiple entries of the same name in the Category list.
My question:
How can I ensure that when I fetch a list of Categories that I get a singular instance of each category, i.e., one category per row in the tableview, with no repeats? Will Core Data automatically assign each new incoming Item to a singular instance of the appropriate Category via the relationship? Or will it somehow test for and winnow the list down to one entry per Category name upon receiving the fetch request? Or must the filtering be done with a predicate in the fetch request?
Thanks!
Core Data will do what you tell it to. This sounds like an issue related to you creating content in your data store rather than an issue with the FRC and table view. It's your responsibility to search for and reuse existing objects rather than creating duplicates and adding them to the store - indeed, only you (your code) knows what constitutes a duplicate.
So, basically, as you create new items, use a fetch request and predicate to find the suitable existing category (or suggest categories based on partially entered names). Then, either connect to the existing category or create a new one.
I am working with Silverlight application with MVVM Concept and Entity framework and having some trouble in inserting the values. Using SubmitChanges method to update, insert, or delete data.
All of the pending changes are submitted in one operation.
Is it possible to use SubmitChanges method twice in one process?
Because I have below requirement:
In First step am inserting data into Table B.
Second step am inserting data into Table A. Here Table A has FK relation to Table B. That's why I am inserting data(Table B) in first step only.
But problem is: submitChange method insert all pending changes at once.
I need to submit the data twice in one process.
Entity Framework will handle the inserts correctly only if you setup the relationships correctly. You do not have to worry about the sequence of the inserts. Entity Framework will sort that out automatically. As a test, open a new diagram of your database and you should see a one to one or one to many relationship between TableA and TableB. If you do not see this relationship, EF will not know how to do the inserts.
Entity Framework will infer the sequence. If you check your object just before the context inserts the record, you should see zero's in the identity columns of both Parent and Child objects. EF will hydrate these properties with the identity values once the record(s) have been inserted.
Say I have a client dataset CDSPerson that acts as a wrapper around a Persons database table. Say I have another table, PersonBenefits, that joins 1:1 back to the Persons table.
Say I wrap a Delphi class around CDSPerson, PersonClass, and another class around CDSPersonBenefits, PersonBenefitsClass, to read and write records. PersonBenefitsClass inherits from PersonClass so it can provide data from both tables. I'd like to be able to write data back to either table through PersonBenefitsClass.
Has anyone developed a clean way to handle the SQL query, provider flags and commit logic in the inherited class so that (a) fields stay aligned with the parent class and (b) both database tables can be updated?
Is there a reference for this that I can't find? Is this just a bad idea? I'm using Delphi 2007.
If you're going to develop a business-object-to-database mapping framework, (commonly known as ORM, Object-Relational Mapper,) you're going to need to put in a bit of architecture to make relationships like this work properly. Here's one way to do it:
PersonClass and BenefitsClass both inherit from BusinessObjectClass. BusinessObjectClass is a base class that contains the general logic to interact with the dataset. It has a list object of some sort that contains a list of relation objects.
Each relation object is a special object that contains either one or a list of BusinessObjectClass descendants, plus extra data describing the foreign-key relationship between the two tables. When BusinessObjectClass does its queries and its updates, it needs to iterate through all its relation objects and have them do their own queries and updates as appropriate.
In your composite object, (PersonWithBenefitsClass,) in the constructor, call inherited and then set up a relation object that describes the related BenefitsClass. Make sure that any inserts of new objects are done in the right order to preserve referential integrity.
That's the basic idea. (One basic idea. There are probably plenty of other ways to do it.) I'll leave the details of exactly how you implement it up to you.
I have an entity (Order) that has a to-many relationship with an entity Item, which has a to-many relationship with an entity Note. If the price changes for a Note, or a Note is added, the 'price' attribute for the associated Order must update.
Right now, my solution is to have all Order objects sign up for NSManagedObjectContextDidChange notifications, and check all the inserted/changed objects to see if any of those objects is one of the Order's Item's Notes. However, this is very inefficient and hacky, and is leading to a few more performance issues that can be optimized away, but I'm starting to realize that my solution is what's faulty, not necessarily the issues.
So, what's the best way to do this?
EDIT: To answer the questions brought up by Rog: I'm looking to propagate the changes to model data, which are observed by view controllers via KVO. The problem I'm noticing is, if the price of a Note related to an Item is adjusted, there's no facility to account for this in Core Data. If I use keyPathsForAffectingPrice on Item, and return "notes", that only accounts for if notes are inserted/deleted, not if the Note price is adjusted.
If this wasn't Core Data, I'd write my own accessor for note price to just say [self.item willChangeValueForKey:#"price"], self.price = x, [self.item didChangeValueForKey:#"price"]; but that isn't possible since I can't do custom accessors in Core Data, right?
We problably need more details about your code to be able to help - i.e. are you looking at ways to propagate changes to your model data or to the UI?
Are you using a fetchedResultsController at the moment?
The way I see it, if your Order contains Items and the Items contain Notes, any updates to your "child" attributes will be effective immediately (provided you have your reverse relationships setup properly).
Then if you're looking at ways to updating your UI accordingly, then we need to know how you are currently fetching and populating your views with your Coredata entities.