Entity Framework detect changes before SaveChanges - c#

I have a Web API that uses Entity Framework and an Angular SPA. I get an entity and pass it to the SPA, but then I get a DTO back from the SPA into my API. Now what is the best way to check to see if the data has changed by someone else?
One possible scenario is to send the original entity along with the modified entity and do a select by the columns I am modifying. If no rows are returned then the data has changed. This might work, but I wanted to see if there is a better way of detecting changes; especially in the case that the data itself is not in an entity but in a DTO.
Thanks.

Related

How to make it explicit in Web API 2 for Entity Framework to only add parts of the object that have changed?

I'm using ASP.NET WebApi 2 and loading in part of a relational database structure into the front end website. This allows the user to make changes to multiple tables in a single store and to also view some extra data.
This mostly works pretty well. It means I can store changes to, say a person table and their related clothes and hair color on one call as follows:
db.person.Add(person);
db.SaveChanges();
The problem is that, I don't want to load all the related data. So where the shoe table may be loaded, I don't want the laces table to load with info about laces.
The issue I'm running into is that there is an attempt to store a duplicate shoe table to the database even though this was only loaded to allow the user to view these details. I imagine that this is because, I'm using [JsonIgnore] attributes to ignore certain parts of the object - it is thus recognizing this as a new object, when it isn't.
I could loop through the object removing any shoe information before call Add, but this would be slow.
Perhaps it is best to post a second object that only includes the items that have changed (after tracking these in the front end). Is there a better way?
When you use DbSet<T>.Add() in EF, the entity (or all the entitis in the tree, if it's an entity with related child entities) is attached to the DbContext as Added. That means that when you call SaveChanges EF will try to insert all the objects in the database. That's why you're getting duplication problems.
You need to learn how to work in disconnected mode with EF. Basically you need to track the state of each entity (i.e. control if they have to be inserted, deleted or updated), and set the correct state when you attach the entities in the context.
Look for docs on working with disconnected entities in EF, for example:
Persistence in Entity Framework
Add, Attach and Entity States
These will explain you how to handle disconnected entities.

Breeze Custom Actions

I've been using BreezeJS in a number of projects for a while now, and I have to say that in most ways, it makes your life MUCH easier, which is why I keep coming back to it. However, I seem to consistently run into a scenario where it falls completely flat, and I cant seem to find any "correct" way of working around this issue.
Let me explain. One of the best things about BreezeJS is that it follow this UoW pattern that allows you to save entities using the saveChanges method of the entity manager, like EF.
However this is also a part of the problem, because as you develop more and more sophisticated application, I sometimes feel this approach is not always appropriate. I find that often I have:
Operations that doesn't really involve creating entities on the client, but rather involve executing an action on the web api that may result in the creation of various entities or other forms of state on the server, that should then be send back to the client.
Operations that involve entities with properties, that cannot be saved because some of them are private to the server, and should not be put on the client (often solved with a JsonIgnore for the client, but comes with issues when you start persisting the given entity again)
I feel that there is one thing that could solve these issues relatively easily, and it is a concept that already exists in OData: Actions. Actions that can be performed globally, on entity sets or on specific entities and then return either custom objects or entities that will be directly tracked by BreezeJS.
Currently, I find myself doing the following workaround (which I don't know if is appropriate):
Make a "Resource" action on the BreezeController that represents an action rather than an an actual resource. This takes in a custom parameter object and returns a non-entity object, that may contain actual entities (as described under "Cool Breezes" with the Lookups, because these will then be track by BreezeJS)
Use the "ajaxpost" breeze lab to allow querying a resource with a POST instead of a GET so any sort of arguments can be passed in.
Is there a more appropriate way of accomplishing something like this? Are there future plans to support custom actions?
An approach I have seen to solve this type of operation, is to simply make these sort of operations "around" the breeze api controller. That is, simply using an ApiController that has nothing to do with breeze. But I kinda feel this defeats the purpose of breeze, because then, if the operation results in the creation or deletion of entities, you must start tracking them by yourself on the client, by either creating them locally, or by issuing another breeze query to go get them. This really gets tiresome if you need a lot of these types of operations.
I’m struggling with the same issue myself. I have an app that uses breeze to store trades in a SQL database and after the trade is stored, another user can use the app to send the trade to a backend trading system. I created an OData action to do the import to the external trading system so I can do a post to /trades(123)/ImportTrade. When I get the metadata for the service using /$metadata it sees that the trades entity has this action (it's in the metadata).
I was hoping that breeze would see this in the metadata and create a method on the trades entity to do a post to my OData action, but it does not. This would be a great feature if it was added to breeze (exposing OData actions as methods on entities).
As a workaround I have extended the breeze entity myself with a custom method that does the post to /trades(???)/ImportTrade.
It would be great if breeze could handle this for us!
Your approach using ajax post is a good way to do thouse kind of things...
You can also make your own context by inheriting from BreezeContext that has nothing to do with a DB, and do your actions there with out saving the entites and still get the result back as a non tracked object or entities.
If you create a new entity on the server (not always a good idea with breeze, but still can still be done) you have to make sure that breeze will still generate the temp keys for that entity.
You can use the temp key generator or just delete the primary keys of the non tracked object.
You can use the metadata of that entity type in order to get it's primary key properties and then delete them using javascript like so: delete obj[prop]
then use createEntity with the non tracked entity that doesn't have primary keys.
Breeze will then generate the primary keys for you and your all set.
I also hope that Breeze will address the need to do custom actions that may return a custom non tracked object in a more intuitive way
Hope this helps

Javascript database with validation based on Entity Framework entities

Is there a way to synchronize local storage with Entity Framework?
What I'm thinking about is for example the following:
A user is completing a wizard in her browser. All necessary data is stored and validated localy based on the entities and validations defined in Entity Framework. In the last step, all this data is transfered from the browser to the server and saved to the database (by EF).
Is there a library for this? Is it even possible at all?
You could use Breeze. This will let you create entities in javascript and sync them with EF.

Persisting Data to the Database from a WCF Servicer

I have a WCF application in C# .NET 4.0. I made all my entity classes and can query a sample from the WCF. The sample is just hard coded values.
Now I am ready to persist these in the database. I am lost on how to approach this though. I plan to create tables for each entity class I created, but what is the best way to add the persistent data layer to my existing WCF application. Is Entity Framework a good choice for this? Thanks for any help or suggestions.
What I suggest is to use entity framework code first. It prevents you from re-creating the model/database by hand. Just set it up so that your current entity classes are mapped to the entity framework and it will automatically create the database for you.
If you google entity framework code first, i'm sure u cant miss it.

'Uncomplete' POCO on client - Can I fill up the collections later?

I have a setup with Client -> WCF -> POCO -> EF4.
Say I have a list with A entities. The A entity contain among other properties a huge list of B entities that isn't loaded by default. When a certain action is done on the client, it may need to know the list of B entities...
If I load the B entities for the A entity and attach them to the collection, the A entity is in effect changed, and I guess when saving the entity it will also save these 'new' B entities to the A entity?
I could wire up a GetEntityWithAllDetails function, but then I would get some data that I already have, and if there were other collections I didn't want to load, it would be a complete mess.
The question can be boiled down to how can I recomplete the POCO on the client side when I only have a partial POCO to start with and want to avoid loading data twice and still being able to rely on EF4 to save the entity correctly?
That is a complex task and EF doesn't handle it - it is your responsibility. When you use detached entities the change tracking is up to you.
Your solution currently probably is:
Client sends request to WCF service
WCF uses EF to get data, close context and return POCO graph or partial graph back to client
Client modifies the POCO graph / partial graph and sends modified data back to WCF service
WCF creates new EF context and saves the POCO graph
Sounds easy but it doesn't. In the last step you must manually explain to the new context what has changed. It generally means heavy interaction with ObjectStateManager (in case of ObjectContext API) or DbChangeTracker (in case of DbContext API). It also means that you must pass information about changes from the client.
For example suppose that you are modifing Order entity. Order entity is dependent on Customer entity and it has dependent OrderItem entities. To make this interesting suppose that OrderItems must be processed by different warehouses so each warehouse has access only items assigned to it.
In the step one you will request Order from one warehouse
In the step two you will retireve Order without Customer and with a supset of OrderItems.
In the step three the warehouse modifies sevaral OrderItems as processed. Deletes single OrderItem because of discontinued product and inserts another OrderItem for replacement of discontinued product. Because of insufficient supplies some items will be unchanged. The warehouse sends Order back to the server.
What will you do in the step four? You must apply some knowledge. The first knowledge is that cutomer was not send to client so you can't modify a customer relation. In case of foreign key relation it means that CustomerId can't be modified. Now you must explicitly say which OrderItem was updated (= exists in DB), which was unchanged (= doesn't need any action), which was inserted (= must be inserted) and the worst part which was deleted (if you don't send some information about deletion from the client you can't know it without reloding the entity graph from the database).
At least you can be happy that EF will not delete anything you explicitly don't mark for deletion. So order items related to other warehouses and their relations to the order will be unchanged.
There are two general approaches how to deal with it:
Load entity graph first and merge changes into the graph. Then save the attached (loaded) graph. You will simply compare the loaded entity graph with the received entity graph and process all required updates, deletes, inserts.
Use self tracking entities instead of POCOs which are implementations of Change set pattern and are able to track changes on the client. STEs have some disadvantages which make them useless in certain scenarios.
There is also completely separate architecture approach using DTOs instead of direct EF POCOs but it results in same complications as you have at the moment.
Welcome to n-tier development.
This sort of situation is exactly why many architected enterprise scale solutions use data transfer objects between tiers.
I would recommend avoiding domain entity propagation from the service (business) tier to the client. If you go down the track of having entities become aware of whether they are fully loaded, or what tier they are currently on, they are hardly "POCO" are they?
So you write a service method "GetEntityWithAllDetails". It should take a GetEntityWithAllDetailsRequest object and return a GetEntityWithAllDetailsResponse object containing whatever the caller of the service expects, and no more.
Obviously there is a far bit of mapping to be done between between DTO's and domain objects - libraries such as Automapper (and others) can help with that.
Propagating domain entities to the client also retricts your flexibiltiy with regards to lazy or eager loading of entities and leaves you having to deal with re-attaching/merging entities, which is problem with EF becuase it will not re-attach entity graphs - you must walk the graph manually.
I will try and say it really plainly. Propagating domain entities from the service to the client is the road to programming hell and very quickly leads to objects having all sorts of responsibilties that are orthoganol to their purpose.

Categories