Entity Framework - Code First, DbSet.Local Not Updating in UI - entity-framework

I have a Code First, CTP5 data context. I have a WPF app with a DataGrid. I set its DataContext like:
dataGrid.DataContext = _context.Customers.Local;
then I add a few entities using
_context.Customers.Add(customer1); and so on
_context.SaveChanges();
Then, I give these customers (a list of the customers) to another class to do some work on them.
customerUpdater.Update(customers);
That takes a long time and it updates properties of each customer while it's working. e.g.
foreach(var customer in customers) { customer.Name = "updated name"; }
I'm not seeing those updates in my WPF UI though! All I see are the original list of unaltered customers. Customers.Local is an ObservableCollection though, so I don't understand why I'm not seeing the updates in the UI.
I don't want to call SaveChanges() every time a property update occurs, it would be nearly constantly. Can someone tell me why this won't update?

If Customers.Local is an observableCollection, and you update the property "name" of one of their items, you are not seeing the updates because you are not modifying the observable collection, what you are modifying is the value of a property of one of the items (customer) present in the observableCollection, but the observableCollection will not send any notifications to the UI because it remains unchanged (it has the same number of items)
If you want the UI to be notified when you update the property name of a customer, you have to make the customer class to implement the INotifyPropertyChanged interface.
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

Related

Entity Framework update with attach or single

I'm new to entity framework and seeing different approaches for updating.
public void Update (Model model)
{
var modelInDb = context.Singe(m => m.Id == model.Id);
modelInDb.Name = "New Name";
context.SaveChanges();
}
public void Update (Model model)
{
context.Customer.Attach(model);
model.Name = "New Name";
context.SaveChanges();
}
Why I should use attach over single? Could you explain difference.
Passing entities between client and server should be considered an antipattern because it can make your system vulnerable to man in the browser and similar attacks.
Your 2 examples don't really outline much because you are setting the updated value solely in your method, rather than based on input from the view. A more common example for an update would be:
public void Update (Model model)
{
var modelInDb = context.Models.Singe(m => m.Id == model.Id);
modelInDb.Name = model.Name;
context.SaveChanges();
}
and
public void Update (Model model)
{
context.Models.Attach(model);
context.Entity(model).State = EntityState.Modified;
context.SaveChanges();
}
In your example, if your method sets the modifications then the UPDATE SQL statement should be Ok, just modifying the customer Name. However, if you attach the model, and set it's state to Modified to save the new model fields to the DB, it will update all columns.
Of these two examples, the first is better than the second for a number of reasons. The first example is loading the data from the context and copying across only the data you expect to be able to change from the view. The second is taking the model from the view as-is, attaching it to the context, and will overwrite any existing fields. Attackers can discover this and use the behaviour to alter data your view did not allow to change. A customer Order for instance might contain a lot of data about an order including relationships for products, discounts, etc. A user may not see any of these details in their view, but by passing an Entity graph, all of it is visible in the web request data. Not only is this going to be sending far more information to the client than the client needs (slower) but it can be altered in debug tools and the like prior to reaching your service as well. Attaching and updating the returned entity exposes your system to tampering.
Additionally you risk overwriting stale data in your objects. With option 1 you are loading the "right now" copy of the entity. A simple check to a Row Version Number or Last Modified Date between your passed in data and the current DB copy can signal whether that row had changed since the copy passed to the client a while ago. With the 2nd method, you can inadvertently erase modifications to data without a trace.
The better approach is to pass ViewModels to and from your view. By using Select or Automapper to fill a view model, you avoid exposing any more about your domain than the client needs to see. You also only accept back the data needed for the operation the client can perform. This reduces the payload size and reduces the vulnerability to tampering. I've seen an alarming # of examples, even from Microsoft, passing Entities around between client and server. It looks practical since the objects are already there, but this is wasteful for resources/performance, troublesome for dealing with cyclic references and serialization, and prone to data tampering and stale data overwrites.

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.

Save One, Save All in Entity Framework

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

WP7: can i use IEnumerable in ViewModel instead of ObservableCollection?

I'm rather new to WP7 dev and I'm trying to play with data binding. I have an XML file and I want to represent it in a ListBox. I've made a ModelView on which I make a Linq query, the result of which I want to put in a ListBox. I've seen that many examples of DataBinding use the ObservableCollection class. I would like to use Linq to get the results instead of looping row by row, but if I use the IEnumerable instead of ObservableCollection, DataBinding does not work. Is that normal?
Silverlight works on a property changed mechanism to be notified when a property has changed in order to update a data binding. You can either use dependency properties (highly unlikely for a view model) or implement the INotifyPropertyChanged interface in your view model class.
In the case of ObservableCollection, it actually raises the CollectionChanged event when it's contents change (add/remove/insert), which also prompts the data binding to update. In your case, by binding to an IEnumerable, the data binding mechanism doesn't know when the contents has changed because there are no events raised.
If every action results in a new list, then you're not gaining anything by creating an ObservableCollection each time you re-query. So you'll need to implement the INotifyPropertyChanged interface and raise property change notification for yrou IEnumerable property when you re-query.
If you have items to add/remove each time you re-query, then creating an ObservableCollection the first time and then calling Add/Remove on each query will work just fine.
I guess it has to be an IList to work. IEnumerable won't work.
Try adding .ToList() to your LINQ query to convert it to List<T>.
As for ObservableCollection<T>, you need to use it if you plan to change items in that collection so that the UI automatically refreshes itself.
You can create an ObservableCollection from an enumerable by passing it to one of the constructors for the OC.
ObservableCollection<Foo> x = new ObservableCollection<Foo>(enumerable);
Courtesy of Cast LINQ result to ObservableCollection
Of course, this only applies if you want to avoid looping through the records yourself and don't have a reason due to behaviour in the code.
but if I use the IEnumerable instead of ObservableCollection, DataBinding does not work
Using an IEnumerable for your list of data items is not the problem, in fact the definition for the ItemsSource property on the ListBox is:
public IEnumerable ItemsSource { get; set; }
Most likely the issue is that your property is not notifying when its value has changed (use the INotifyPropertyChanged interface).
The ObservableCollection type is a collection that implements INotifyCollectionChanged, so you can easily tell when the collection itself has changed, although this doesn't notify you when the properties on the collection items themselves have changed. It also implements INotifyPropertyChanged, which is most likely why your data binding was working on your property in your ViewModel. The reason why the ObservableCollection is good to use in this case is because you can just add and remove items to the collection to update the list based control, you don't have to rebind it (or rebuild a list).
So if you bind to a IEnumerable<> property, make sure you raise a notification that the property has changed, and be aware that adding/removing individual items will not get reflected automatically in the UI unless you devise a way of notifying that the bound property has changed (which would be a bit of a hack).

How to notify all properties of the view model has changed

In MVVM pattern, how to notify all properties of the view model has changed? I don' t want to call all notifypropertychanged event of all properties.
I have an entity class and in view model I wrote all of the public fields of the entity as public properties. I want to rebind new entity and just write a single line of code to notify that all properties has changed?
Thanks for your help.
Just raise the PropertyChanged event with an empty string as the property name :
OnPropertyChanged(String.Empty);
Ok what I understood from your question is this..
View <> ViewModel <> Entity (with a bunch of properties)
View is bound to ViewModel, which delegates to Entity. You now want to replace the backing entity and signal the view to refresh to update to the newer entity.
I'd suggest implementing an indexer in the ViewModel which takes in a string (the name of the backing property). The ViewModel can be used as a cache if required, delegating to the backing entity only on a miss.
When you replace the entity, the viewModel clears its cache and fires NotifyPropertyChanged (in the indexer set) with String.Empty or null. Which I learned today, indicates all properties have changed.
This way you don't create n delegating properties in the ViewModel. A google search result shows that it has been tried at least once with success.