I have a Answer table which has pk_answerid, answertext , fk_questionid, chosenoptions stored as 1,3,2 (comma separated)
answertext if populated, then chosenoptions null and if chosenoptions if populated then answertext is null.
ChosenOption table has structure pk_chosenoptionid, fk_questionid
In EntityFramework 4,
I have something along these lines
void SaveAnswers(ICollection<Answer> answers)
{
context.Answers.Add(answers);
context.SaveChanges();
}
This works fine....but when in the UI I go back to page which is wizard with Q&A's on different pages and I deselect all answers previously selected, and click save, no answers are deleted. I also tried DeleteObject which does not delete the Answers and chosenoptions even though I have cascade delete on the Answer table to Chosen option table.
Also in edit scenarios if for e.g. if the User selected option 1,2 and then saves it and then goes back and selects 3,2 how do you write code in EF to do such complex stuff. I haven't come across any tutorials which explain such scenarios. Most of what I have seen is simple add, delete and applypropertychanges. I have an MVC app, which has lazy loading enabled.
Pls help and suggest some sort of code using an example or any pointers to existing blogs where this is explained.
EF doesn't take care - I shame to posting this again and again but I really don't like to explain it every time: Update relationships when saving changes of EF4 POCO objects
Check that explanation. Your problem is similar. You persisted entity graph (set of related entities) and now you want to change the graph. Your new graph is extracted from web request which mean it is detached and EF doesn't know what has changed. You must do it manually - I just discussed what does it mean to do it manually in another question = it is usually too complex.
The easiest way is your current approach - delete everything and add it again but it is really ugly. Another approach is loading the graph from database and manually merge all changes you get from the request = compare these two graph and update the loaded (attached). Be aware that you must manually call DeleteObject for anything you want to delete from the database. Then just call SaveChanges.
Btw. if you are doing wizard why don't you just store current state in session and save everything once user completes the wizard? You will avoid all these complications.
Related
How do I pass a session variable to the Insert, Update, Delete stored procedures mapped to a Table in an Entity Framework, and how do I get the mapping in the EDMX diagram to work with it?
I have a database with Stored Procedures (SPs) defined for Inserting, Updating, and Deleting rows. The SPs expect a userid parameter to be passed to them for audit trail purposes, this parameter does not exist as a column in the table.
When I'm in the EDMX diagram specifying the mapping for the Parameter I don't see any way to either a) ignore the parameter or b) (preferred) set the value to a Session value. I've created a partial class mapping of the Stored Procedures, however the model doesn't seem to see it or even acknowledge that it is there. The whole premise behind using this technology is to let it do the work. I can't even tell it to ignore this parameter as it is optional and has a value assigned to it. I can't even edit the SP definition as the file is marked autogenerated, and will lose any modifications when it is regenerated.
Entity Framework seems like a well thought out approach, and I've looked at several tutorials and books on the subject. However, this seems like a really obvious thing to do. I've looked through stack overflow and the MSDN forums and found similar questions from years ago, but no one ever seems to answer the question, they just dance around the issue.
I'm still learning about Unit of Work patterns, repository patterns, etc.
My app:
I have a list of entities, say customers in a listview
When I select a customer a detail form shows, where their details can be edited
I'm trying to understand the standard MVVM/Entity Framework way of accomplishing the following:
When the user edits a customer it shows as "changed" (but not saved)
The user can chose to either save the current customer, or save all the changed customers
The Save or Save All commands/buttons are disabled if that option is not available (the current customer is unchanged, or all customers are unchanged)
Seems simple enough? But I have no idea how to approach this using MVVM/EF. Do I use UoW, do I detach objects and re-attach to the context so I can save them one at a time? How do I detect if an object is changed or unchanged?
Help! Thanks!
I throw in a few remarks:
The critical point in your requirements is in my opinion the option to save either one single customer or all changed customers. You need to take into account that Entity Framework doesn't have a method to save changes of a single or a few selected objects in the context. You can only save the changes of the whole Unit of Work (which is the ObjectContext or DbContext in EF) by calling myContext.SaveChanges().
This leads to the conclusion that you cannot use the list of all customers and the customer detail form in one single Unit of Work (= EF context) which holds all customers as attached entities. If you would do this you could provide a function/button to save all changes but not an option to save only the current customer in the form.
So, I would either think about if you really need those functions or I would work with the entities in a detached state. This would mean that you have to load the customer list from the database and dispose the context after that. When you save the changes - and now it doesn't matter if all changes or only changes of a single customer - you can create a new context, pull the original entity/entities from the database and update with the changed properties.
But working with either attached or detached entities - or either having one living EF context per view/form or creating only one short-living context per CRUD operation - is an important design decision in my opinion. Generally the possibility to have your entities attached to a context during the lifetime of a view/form exists to make your life as programmer easier because it offers you features like lazy loading and change tracking out of the box. So you might think twice if you want to give this up.
To recognize if a customer object has been changed or not the EF context could be helpful because it tracks the state of an object. You could for instance query the ObjectStateManager for a customer and check if it is in a "Changed" state. But to have this option you would need to work with attached entities as explained above. Since you cannot save (or also cancel) single object changes it is questionable if it would make sense at all to show the user that customer 1 and customer 3 has changed. (I would probably only show "some customers have changed".)
If you are working with detached entities you have to manage by hand which customers have changed or not by implementing some kind of "dirty flag" logic. Here is a thread about this:
Different ways to implement 'dirty'-flag functionality
I would like to know when entities in a certain database table are either created or updated. The application is essentially a CMS, and I need to know when changes are made to the content so that I can reindex them for searches.
I know that the autogenerated LINQ to EF class has overridable methods for when certain fields change, but I need to know when the whole object is created/updated, not just a single field. I tried putting it in OnCreated, only to find that meant OnObjectInitialized and not OnObjectInsertedIntoDBTable xD
I did some searching and came across this link. The "Entity State" section looks like its what I want, but I'm not sure how to use this information. Where do I override those methods?
Or perhaps there is a another/better way?
(I also need to know this for another part of the system, which will send notifications when certain content is changed. I would prefer this code to execute automatically when the insert/update occurs instead of placing it in a controller and hoping hoping I always call that method.)
You need to get ObjectStateEntry(s) from the ObjectStateManager property of the ObjectContect.
var objectStateEntries = this.ObjectStateManager.GetObjectStateEntries();
This entries contain every object state you've pulled down per context and what kind of actions where performed on them.
If you are using EF4 you can override the SaveChanges method to include this functionality. I've used this technique to audit every change that occurs in the database instead of triggers.
I would like to know if there is some kind of similar functionality or way to preform an "on duplicate key update" function with core-data as there is with MySQL.
What I want to do is to save an object to the database every time a user presses a button. But if the button is already pressed I want to update the row with some new values instead of adding a new row.
The only way I currently know how to do this is to read the rows from the DB, see if the row exists and then update it.. otherwise add a new row. This seems kind of bad to do this way, am I wrong?
The easiest answer to this is to run a query against the Core Data context and get the object back if it exists. This is the most efficient and least error prone solution to the problem.
You do not need to create a separate NSManagedObjectContext and attempt to deal with merge policies, that is a very inefficient and dangerous way to try and resolve such a simple issue.
Core Data handles a lot of caching for you in the background. If you are attempting to retrieve an object that you just created there is a very high probability that it is still sitting in the cache so the response to your query will be nearly instantaneous.
Note
I just went back to both of those sample projects again to file a bug against them and noticed that they have been updated and finally removed the suggestion of creating a new context. They are now using the NSUndoManager where appropriate and a single context.
EDIT
Remember that the core data framework manages persistence of your object graph. It is not an interface to a sqlite database.
Worry about your object life cycle. When do instances get created? When are they destroyed? What makes your instances unique? Using Books as an example entity, a book has an ISBN which is a unique way of identifying a title, yet many copies of each title can exist. You have two choices in your Entity model, you can create separate instances for each copy of the title or have one instance with a count attribute.
The sample projects CoreDataBooks and iPhoneCoreDataRecipes use NSUndoManager to track state changes between views.
I have a requirement to only save data to a table in a database (I don't need to read it)
If the record already exists I want to update it otherwise I will add it.
It usually exists.
My entity context might already hold the object .. if it does I want to find it and use it again without causing it to refresh from the database when I 'find' it
i.e. The context holds a collection of entities (rows of a database) I want to find an entity in the collection and only want the context to go to the database if entity is not in the collection. I don't care about the current values of the entity .. I just want to update them.
Hope this is clear ..... thanks
I may not be quite seeing the question, but I believe your looking for some sort of caching mechanism, I know for work we use devForces IdeaBlade which does the trick, however I believe you can create a simple caching mechanism custom to you needs.
Link
The bits on caching will be helpful, if this doesnt help tell me and I can dig a little deeper.
I believe you need to use GetObjectByKey() instead of using an ObjectQuery I believe an ObjectQuery always hits the backend datastore whatever it may be.
More Info here http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.getobjectbykey.aspx