I am using Entity Framework 4 with the Service/Repository/EF4/POCO classes technique, and I have a question about View Model binding.
When you map a class to a view model and only take the fields the view needs, then map it back to a new instance of the class to persist to the database, how do you prevent the fields not used in the view from getting overwritten?
This is usually performed by loading entity from db first and merging incomming data to this entity (ObjectContext will track changes and update only changed properties). Another approach is manually set which properties where modified in state manager:
context.MyEntities.Attach(entity);
context.ObjectStateManager.GetObjectStateEntry(entity).SetModifiedProperty("Name");
Now when you save changes only Name property of the entity will be included in Update SQL command.
When using repostiory check high level example I shown here.
Related
I need to be able to create new core data entities during runtime. I've written the code to create the objects programmatically, however, I can't add the entities during runtime as the model is immutable.
My problem is similar to this post, however there is no satisfactory answer: How to dyanmic create a new entity (table) via CoreData model?
The documentation regarding changing the core data model explains:
Managed object models are editable until they are used by an object
graph manager (a managed object context or a persistent store
coordinator). This allows you to create or modify them dynamically.
However, once a model is being used, it must not be changed. This is
enforced at runtime—when the object manager first fetches data using a
model, the whole of that model becomes uneditable. Any attempt to
mutate a model or any of its sub-objects after that point causes an
exception to be thrown. If you need to modify a model that is in use,
create a copy, modify the copy, and then discard the objects with the
old model.
However, I'm unclear on what exactly this is saying--that the whole core data model can't be changed once the persistent store coordinator has been used or the attributes/etc of the individual entities can't be changed.
To be clear, I do not want to change the attributes of my current entities, I simply want to add new entities. It just seems weird to me to have to use migration to add new entities.
Any thoughts?
Thanks!
The documentation is pretty clear.
Copy the model.
Apply your changes to the new copy.
Destroy your old MOC, Persistent Store Coordinator, and all objects created from those.
Apply a migration, if necessary.
Create a new Core Data Stack (MOC, PSC, etc) using your updated model.
The migration could be a sticking point, but it should be do-able.
First of all I want to ask that what is the difference between Entity Class and our Model Class ?
And when I use to add Data Annotations on the Entity Classes generated by the Entity Framework in Database approach, it's vanished upon every "Update From Database", and for this user defined Model Classes can be used but I have no idea to use them with the generated Entity Classes.
An entity class is a class that directly associate's with a real object and is linked to business logic and holding information about the system. Entities are usually used to establish a mapping between an object and to a table in the database.
Models are simply classes that are associated with a views and controllers which define or contains the definition of an object and when there has been a change in state. These can hold your data annotations to validate before going up to the Business/Data Access layers...
This leads me on to your next question and if using EF to generate your data model classes using the "database first" approach, then you cannot apply the data annotation attributes directly to your classes. Because the EF Designer generates the model classes, any changes you make to the model classes will get overwritten as you have been experiencing. If you want to use the validators with the classes generated by EF then you need to create meta data classes: http://blogs.microsoft.co.il/blogs/gilf/archive/2011/01/20/adding-metadata-to-entities-in-the-data-model.aspx
Hope that helps.
Danny
I'm using MVC.net and I have 2 classes (case and accident) with a many to many relationship, I'm also using auto mapper to copy View Models to EF and vice versa. Now the problem i've come across is when i do this:
Case theCase = Mapper.Map<CaseEditVM, Case>(theCaseEditVM);
theCase.Accidents.Clear();
UOW.Cases.Update(theCase);
The changes to the case are saved but the link table for accidents is not. Ef totally ignores the Accidents changes.
However when i do:
Case theCase = UOW.Cases.GetByID(someid).Include("Accidents");
theCase.accidents.Clear();
UOW.Cases.Update(theCase);
EF correctly saves the accidents property.
So from what i can tell EF ignores the accident property as its not mapped inside EF yet. Make sense however how do i tell it when mapping the View model i want EF to update the linked properties as well?
The simplest way in your case is first attach case to context and clear changes after you attached it. Otherwise you will have a lot of work. There is no magic which would make this for you. EF doesn't know about changes to relations you did on detached entity and what is even worse once you attach the entity to context you already don't know what records were included in the navigation property so you cannot configure context to reflect that (it must be done per every single related entity) without reloading the whole entity and merging changes between detached and attached one.
I'm trying to create a POCO proxy for an entity already known to be in the database--similar to the nHibernate Session.Load().
I'd like to set the ID value and then if any other properties are accessed on the entity, the other properties are lazy-loaded--again, similar to the nHibernate Session.Load()
I've tried creating a proxy with ObjectContext.CreateObject(), setting the ID value, and attaching it to the context. But the properties don't lazy-load when accessed. The navigation properties, however, will lazy-load just fine.
I'd like this functionality for cases where I need an entity and know the ID, but don't want to force an extra database hit to load the entity. I also want to ensure that the properties can be loaded in the event that they are needed.
Is this possible with Entity Framework 4?
No it is not possible. The reason is that Entity framework supports only lazy loading of navigation properties. You cannot lazy load scalar or complex properties. You must load the entity from database to get them filled.
I am not sure if that makes any sense, but here is an example.
I have a Category object, that my Service hands to the Controller, which uses AutoMapper to create a CategoryViewModel. Hand that off to the view, serve it to the client.
Now when that gets posted back, AutoMapper creates a Category from the Model sent back, and I hand it to the Service that gives it to the Repository to persist to the database.
My question is, what is the correct way of doing this? I assume the object is a detached object when posted back and I need to attach it to the context, mark it dirty and save changes?
Basically two ways of doing the update of the entity:
Attach the entity to the context, mark it as modified using ObjectStateManager.ChangeObjectState Method, call ObjectContext.SaveChanges Method
Load the original entity from DB, apply changes to the original using ObjectContext.ApplyCurrentValues<TEntity> Method, call ObjectContext.SaveChanges Method
Each of those have their own pros and cons. For example the 1st one does not make round trip to get the original entity but fails to address concurrency as well as tries to update every property of the entity, while the 2nd one works best when employing optimistic concurrency, updates only changed properties, but it does make extra trip to Db to get the original entity.
"I assume the object is a detached object when posted back and I need to attach it to the context, mark it dirty and save changes?"
Yes.
Any one of the links on this page should help:
http://www.google.com/search?rlz=1C1CHFX_enUS410US410&sourceid=chrome&ie=UTF-8&q=working+with+dicsonnected+entities+entity+framework