How to Improve Entity Framework and Javascript Interaction How to Improve Entity Framework and Javascript Interaction ajax ajax

How to Improve Entity Framework and Javascript Interaction


There are a few improvements to be made.

Save() Method - Don't left-to-right copy, use EF built in logic

Instead of this:

myEmp.Employee_ID = emp.Employee_ID;myEmp.First_Name = emp.First_Name;myEmp.Middle_Name = emp.Middle_Name;myEmp.Last_Name = emp.Last_Name;myEmp.Supervisor_ID = emp.Supervisor_ID;myEmp.Active = emp.Active;myEmp.Is_Supervisor = emp.Is_Supervisor;

You can do this:

ctx.Employees.ApplyCurrentValues(emp).

What this does, is look for an entity with the same key in the graph (which there is, since you have just retrieved it with FirstOrDefault()), and override the scalar values with the entity you pass in - which is exactly what your doing.

So your 7 lines becomes 1, plus if you add any extra scalar properties - you won't have to refactor your code. Just remember - only works for scalar properties, not navigational properties.

Why build query for primary key retrieval? Just use predicate to SingleOrDefault()

Instead of this:

var results = from item in ctx.Employees              where item.ID == emp.ID              select item;var myEmp = results.FirstOrDefault();

Do this:

var myEmp = ctx.Employees.SingleOrDefault(x => x.ID == emp.Id);

Or even better, use a pipe/filter technique:

var myEmp = ctx.Employees.WithId(emp.Id).SingleOrDefault();

Where WithId is an IQueryable<Employee> extension method, which filters the query based on the supplied employee ID. This allows de-coupling of filtering/business logic from your repository/DAL. It should go in your domain model, so you can have a nice fluent API for query your domain entities via your ORM.

When your retrieving an entity via the primary key, you should always use SingleOrDefault() or Single(), never FirstOrDefault() or First(). If it's a primary key - there should only be one of them, so you should throw an exception if more than one exists, which is what SingleOrDefault() does. And as @Shiraz mentions - your FirstOrDefault() will crash the query below. You always need null checking when you use <First/Single>OrDefault().

The same improvements can be made to your Get method.

Overall, there is nothing functionally wrong with your code - it just needs subtle improvements, null checking and exception handling.

The only functional improvement i highly recommend is refacting your web service code into a Generic Repository. As the code is very trivial and can be re-used across any entity. The web service shouldn't be concerned with transactions, primary key's or EF logic whatsoever. It shouldn't even have a reference to the EF DLL. Encapsulate this logic behind a repository and delegate the persistence logic to there (via an interface of course).

After making the changes i've mentioned above, your web service methods should have no more than 5-7 lines of code each.

You have far too much intelligence in your web service - it should be dumb and persistent ignorant.


I find that it's usually a pretty bad idea to try and use my entities directly on the data contract. It's possible, and works fine in certain cases, but anytime my object model gets even a little complex I start having to worry about the object graph in ways that I don't want to have to.

Instead, and this is regardless of the client, but it's applicable to a JS client just as much, I try and think of the data contract classes as pure data trucks (DTOs) with no mapping in EF at all. Those classes are just he documents I'm passing back and forth, the message body if you will. They might translate into commands on my model or they might be used to populate a query, or whatever, but they're not the entities themselves.

This, I find, simplifies things a great deal. It may feel like more code when you first write a simple service, but over the lifetime it makes things a great deal more maintainable.

And just as a side note, you should also consider separating your responsibilities a bit better. The web service class should not have the responsibility of directly creating adn disposing of the data context, it should depend on a DAO or repository interface (or domain service) which handles all that stuff for you (and applies transactions as needed, etc).


Your get method can crash.

If this line returns null:

   var emp = results.FirstOrDefault();

Then this line will crash with a null reference exception:

   where item2.Employee_ID == emp.Employee_ID

I would also put in some try catch blocks in with logging of errors.