Entity Framework Audit log - Tracing changes in virtual objects - entity-framework

Based on how to create an audit trail with Entity framework 5 and MVC 4 question I am trying to figgure out how can I track changes in virtual/foreign objects.
On the line which compares the OriginalValues to the CurrentValues it does not include the fields for the virtual objects that where changed.
if (!object.Equals(dbEntry.OriginalValues.GetValue<object>(propertyName), dbEntry.CurrentValues.GetValue<object>(propertyName)))
Is there an easy fix for this where I can specify in my controller method that x and y virtual objects might also have been changed? Or maybe look up the original and current values of those connected to the current dbEntry in the dbEntry.State == EntityState.Modified section?

Related

Confused about core data one-to-many configuration

Essentially I am creating an app that tracks packages - 1 tracking number to many - detailed updates for that tracking number.
For example:
Parent: Tracking #: 102391249
Tracking Updates:
Child1: Departed Location
Child2: At Local Fedex Facility
Child3: Delivered
The following is my current setup, the image on the left being the parent and right being the child:
Was this setup correctly? I am new to CoreData but coming from my knowledge of relational databases I am trying to make sure the id in the parent in the trackingid of the child to create the connection between the 2 "tables"
Set the one to many relationship between the Numbers and Details entities to connect the two entities. When you create an instance of the Details entity in your code, set its relationship to a Numbers entity.
child.numbers = parent
Where child is an instance of the Details entity and parent is an instance of the Numbers entity.
The numbers (changing the name to number would be clearer) relationship that you have in the Details entity gives you access to the tracking number. You can access the tracking number using the relationship and the Numbers entity's tracking number attribute.
let trackingNumber = child.numbers.trackingnumber
Since you have access to the tracking number from the relationship, you can remove the trackingid attribute from the Details entity.
By the way consider using clearer entity names than Numbers and Details. Your app deals with tracking shipping updates to packages. I recommend renaming Numbers to Package and Details to TrackingUpdates or ShippingDetails.

Change/Status tracking in entity framework 6

My question relates to overall design within entity framework 6. My model has an entity type called Person. Each person consists of multiple values, some of which it is important that i track the previous values of these properties. An example of that includes Last Interaction Date and Status
The model currently has a separate entity for each property i wish to track historical status on in this case Person_Status and Person_lastInteraction; the relationship is created with a 1 to many relation.
I extend the Person partial class to allow methods for updating the these tracked properties.
....There has to be a better way!
My Concerns:
Every time i want to track a different property i have to create a new entity just for tracking those particular property changes, requiring DB changes
Because EF still exposes the property its possible someone could change the person status without using the methods added to the class.
I'm re-writing a lot of the same exact code to do essentially the same thing
Has anyone encountered a situation as such, what did you do?

Add or update in Entity Framework, complex deserialized objects

We're creating a WebAPI using Entity Framework in MVC 4. Our client wants to send complex objects containing related objects - both new and updated. The root object maybe new or existing one too. The client generates primary keys - we're using Guids for that. So on server we really can't tell that we got an existing object update or a new one. What would be the best way to handle this situation? We need some sort of add or update functionality and it's not yet clear to us how to proceed with Entity Framework for this.
EF doesn't have any build in support for discovering changes in detached object graph. You either have to include some field into every object describing if the object is new, not modified, updated or deleted (you will also need similar behavior to track changes in many-to-many relationships). If you don't use such field you have no other way than querying database and comparing current DB state with data received from client to find what has changed.

Is it possible to tell if an entity is tracked?

I'm using Entity Framework 4.1. I've implemented a base repository using lots of the examples online. My repository get methods take a bool parameter to decide whether to track the entities. Sometimes, I want to load an entity and track it, other times, for some entities, I simply want to read them and display them (i.e. in a graph). In this situation there is never a need to edit, so I don't want the overhead of tracking them. Also, graph entities are sent to a silverlight client, so the entities are disconnected from the context. Hence my Get methods can return a list of entities that are either tracked or not. This is achieved dynamically creating the query as follows:
DbQuery<E> query = Context.Set<E>();
// Track the entities in the context?
if (!trackEntities)
{
query = query.AsNoTracking();
}
However, I now want to enable the user to interact with the graph and edit it. This will not happen very often, so I still want to get some entities without tracking them but to have the ability to save them. To do this I simply attach them to the context and set the state as modified. Everything is working so far.
I am auditing any changes by overriding the SaveChanges method. As explained above I may, in some low cases, need to save modified entities that were disconnected. So to audit, I have to retrieve the current values from the database and then compare to work out what was changed while disconnected. If the entity has been tracked, there is no need to get the old values, as I've got access to them via the state manager. I'm not using self tracking entities, as this is overkill for my requirements.
QUESTION: In my auditing method I simply want to know if the modified entity is tracked or not, i.e. do I need to go to the db and get the original values?
Cheers
DbContext.ChangeTracker.Entries (http://msdn.microsoft.com/en-us/library/gg679172(v=vs.103).aspx) returns DbEntityEntry objects for all tracked entities. DbEntityEntry has Entity property that you could use to find out whether the entity is tracked. Something like
var isTracked = ctx.ChangeTracker.Entries().Any(e => Object.ReferenceEquals(e.Entity, myEntity));

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.