find a location for property in a new city

Monday 28 March 2011

How to delete an entity by ID in Entity Framework

It may seem unnatural to delete Entities in Entity Framework. In the days of stored procedures I used to just pass an ID where as now you need to get the entity before deleting it. It seems inefficient - you're basically making two database hits when surely you can do it in one database call, right? Well it is difficult but entirely possible.

Since you do not have the entity you will need you will effectively be updating a detached entity which is a technique in itself. The trick here is that we are making a fake entity that shares the Entity Key (EF version of a primary key) with the one that needs deleting. Then we mark it as deleted and SaveChanges.

public void DeleteByID(object id)
{
    //make fake entity and set the ID to the id passed in
    var car = new Car();
    car.ID = id;

    using (var context = new MyDataContext())
    {
        //add this entity to object set
        context.CreateObjectSet<Car>().Attach(car);
        //mark it as deleted
        context.ObjectStateManager.ChangeObjectState(car, EntityState.Deleted);
        //save changed - effectively saying delete the entity with this ID
        context.SaveChanges();
    }
}

It is worth noting that I am following my own twist on the Repository pattern for data access so I have an "EntityRepository" that manages everything EF related. This is where I will make my generic "DeleteByID" method. My EntityRepository uses generics to specify the type of entities that are dealt with so this has to be completely reusable by any entity set (TEntity) or object context (TContext).

How to Delete by ID in a generic way

public void DeleteByID(object id)
{
    var item = new TEntity();
    var itemType = item.GetType();

    using (var context = new TContext())
    {
        //get the entity container - e.g. MyDataContext - this will have details of all its entities
        var entityContainer = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
        //get the name of the entity set that the type T belongs to - e.g. "Cars"
        var entitySetName = entityContainer.BaseEntitySets.First(b => b.ElementType.Name == itemType.Name).Name;
        //finding the entity key of this entity - e.g. Car.ID
        var primaryKey = context.CreateEntityKey(entitySetName, item).EntityKeyValues[0];
        //using Reflection to get and then set the property that acts as the entity's key
        itemType.GetProperty(primaryKey.Key).SetValue(item, id, null);
        //add this entity to object set
        context.CreateObjectSet<TEntity>().Attach(item);
        //mark it as deleted
        context.ObjectStateManager.ChangeObjectState(item, System.Data.EntityState.Deleted);
        //save changed - effectively saying delete the entity with this ID
        context.SaveChanges();
    }
}

These both translate to the following SQL:
delete from [dbo].[Cars]
where  ([ID] = 123)
And there it is - a reusable delete by ID function with no SELECT!

Follow britishdev on Twitter

Friday 18 March 2011

How to update a detached entity in Entity Framework

If you are using Entity Framework and closing or disposing of your DataContexts (read database connections) as soon as your Linq to Entities query have finished, which I believe you should, you will run into the situation where saving changes to an updated entity will be ineffectual.

I've discussed before that I think deliberately keeping database connections open is bad in Entity Framework but when practicing this technique you will find saving changes to an updated entity no longer works as it used to when the DataContext was left open as long as it liked.

This is because when you open a DataContext you are also starting up change tracking. Change tracking will keep a note of if your entity has been changed. This is important when you call SaveChanges on that DataContext because it needs to know if there have been any changes to save.

If, however, you open your DataContext, do you Linq to Entities query to get an entity and then dispose of your DataContext your entity is now detached. To SaveChanges you will need to open an new DataContext, which will have no idea that this entity has been changed. So you need a way to update a detached Entity.

Update a detached entity with your DataContext

You can do this by using the Attach method to attach this entities to the DataContext (so it is now managing it). After you've attached it it will be in the "Unchanged" state so will not do anything on SaveChanges. You can tell it it has been updated by changing its object state to Modified. Then simply save changes.

Here is an example. (This is not my actual code - it is more explicit to aid understanding):

public void UpdateObject(T obj)
{
    using (var context = new MyDataContext())
    {
        context.CreateObjectSet<T>().Attach(obj);
        context.ObjectStateManager.ChangeObjectState(obj, EntityState.Modified);
        context.SaveChanges();
    }
}

Updating a detached model when using EF Code First

Coming back to my blog years later (Feb 2013) to reuse the above code I found it didn't work in Entity Framework Code First Model. This is because the context mentioned above is a different from the DbContext used in Code First and so has different properties and methods. Here is the code I used to make this work in EF Code First:

public void UpdateObject(T obj)
{
    using (var context = new MyDataContext())
    {
        context.Set<T>().Attach(obj);
        context.ChangeTracker.Entries<T>().First(e => e.Entity == obj)
                                              .State = EntityState.Modified;
        context.SaveChanges();
    }
}

Follow britishdev on Twitter

Firefox loses Request headers after redirect

Firefox does not remember some request headers after a redirect. This can cause problems with AJAX requests that use the X-Requested-With: XmlHttpRequest header.

I noticed a little problem with Firefox. In my scenario I have added the SEO optimising IIS Url Rewriting module pattern that redirects URL with upper case in to a lower case version.

For all browsers the AJAX request comes in with the X-Requested-With: XmlHttpRequest request header, a 301 status code is returned with the lower cased location, that new location then is requested with the X-Requested-With: XmlHttpRequest header in tact.

Firefox, however, does not honour this header in its redirect. This causes problems with my ASP.NET MVC code that checks for the request being via AJAX using IsAjaxRequest(). This method checks if X-Requested-With: XmlHttpRequest is in the headers (or in other exciting places).

Work around

I was going to try and do something clever like detect the browser and this header and then not redirect under some circumstances because (brace yourself SEO consultants) functionality is more important than SEO. I decided to instead make sure that one troublesome link was lowercase and so avoided the redirect.

Just hope this answers your questions if you come across this oddity in Firefox.

Follow britishdev on Twitter

Wednesday 16 March 2011

WCF REST: How to get a Request header

Again WCF REST is proving secretive when it comes to getting at your Request Headers.

You can get at any custom Request headers that you may be expecting via the IncomingMessageProperties off of the OperationContext in the same way as before when you were adding custom Headers to your response.

To do this you you can write something like this:
var request = OperationContext.Current.IncomingMessageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
var version = request.Headers["ApiVersion"];

Update:

Actually, there is an easier way I found. Since this is in a REST service it is possible to use WebOperationContext which seems a lot more intuitive and concise:
var version = WebOperationContext.Current.IncomingRequest.Headers["ApiVersion"];

You will then have access to any expected Request Headers as a string.

More WCF REST:

Follow britishdev on Twitter

WCF REST: How to add a response header

I can't believe how difficult it is to add a response header to a response to a WCF REST service. It is so round the houses it really quite difficult.

Whatever happened to Response.Headers.Add from the friendly web code I'm so used to... Oh well, after scratching around for ages I finally found how:
var prop = new HttpResponseMessageProperty();
prop.Headers.Add("ApiVersion", "v1.0");
OperationContext.Current.OutgoingMessageProperties.Add(HttpResponseMessageProperty.Name, prop);

I know you're kicking yourself, right? "That's so obvious..." Ridiculous - I'm starting to thing WCF REST wasn't made with the developer in mind.

Update:

Actually, there is an easier way I found. Since this is in a REST service it is possible to use WebOperationContext which seems a lot more intuitive and concise:
WebOperationContext.Current.OutgoingResponse.Headers.Add("ApiVersion", "v1.0");

More WCF REST:

Follow britishdev on Twitter

WCF REST: How to get the requested URL

Finding the Request.Url is a lot different from standard web work when working in a WCF REST context. It can be quite difficult to find the URL of the request in your WCF REST service.

I found you can do it with the following code:
var context = OperationContext.Current;
var requestedUrl =  context.IncomingMessageHeaders.To.PathAndQuery;

So there you are... enjoy.

More WCF REST:

Follow britishdev on Twitter

WCF REST: How to get an IP address of a request

It seems to be quite difficult to find the IP of the request when in the Context of a WCF REST service.

I found you can do it with the following code:
var props = OperationContext.Current.IncomingMessageProperties;
var endpointProperty = props[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
if (endpointProperty != null)
{
    var ip = endpointProperty.Address;
}

This seems overly verbose so you may want to consider putting this code into helper methods or a base class for re-use.

More WCF REST:

Follow britishdev on Twitter

Friday 4 March 2011

Why you shouldn't use singleton DataContexts in Entity Framework

I have been struggling recently with putting an end to a problem caused my optimistically keeping the same DataContext alive in a singleton pattern. Let me tell you what I found and why I think it is bad.

Getting it wrong will cripple your site

The first and foremost reason why you shouldn't use it is that if you set it up wrong the repercussions are critical. Here's my horror story: after ages of head scratching, wondering why the CPUs are continuously nearing 100% and memory leaks are ubiquitous I finally figured out that DataContexts were not being disposed of. Of course this is by design - lovely singleton pattern...

Anyway, not only were they not being disposed of they were being instantiated with every access of the data. So we ended up with piles of open connections, which I assume were being terminated randomly by some critical process. This causes huge memory utilisation and huge CPU usage trying to reallocate memory.

Fine so it was implemented incorrectly, but it is practically impossible to see that this is happening during development without shelling out for a decent entity framework profiler (like Entity Profiler - it is very much worth it if you don't trust EF).

Data isn't in sync sometimes...

When we were using the singleton well the data often seemed out of sync with the database. It's as if the ObjectContext knew best and didn't really care what the database had to say. This is not wise when you are working on a web farm since your different servers will have a different view of what the data is in its memory.

The way to resolve this is to begin a new connection... In comes the problem of multiplying open and undisposed connections.

Where's the performance gain anyway?

Has anyone any idea of how expensive it is to open a DataContext connection? Answer: "A DataContext is lightweight and is not expensive to create" [citation]. So why is everyone so intent on saving the hassle of creating a DataContext?

You are probably saving a few 10s of milliseconds. The word micro optimisation springs to mind - in which case you probably shouldn't be using Entity Framework.

It allows poor coding

Having a DataContext that is never closed allows you to lazy load whenever you want. You may have left your Service and now be in your Controller or worse still, your View. Accessing the database from a View is asking for performance problems as I'm sure you didn't allow that intentionally. It is most likely because you forgot to eager load all the data you need to populate your view.

This also makes it hard to keep things nice and streamlined since you don't know where all your queries are coming from.

Conclusion

If you are a guru of Entity Framework and you think a Singleton DataContext is for you then by all means go for it. If you aren't convinced you need it and you're just experimenting you could encounter unexpected and serious problems. Don't use singleton because you think it sounds cool!

Also, during fixing up my problems I found the Entity Profiler invaluable. It tracks how many connections have been opened and closed (hopefully they will be equal). It also shows all the actual SQL that is being produced, the results, the query plan and even tips on how to sort your query out. Invaluable!

Follow britishdev on Twitter

Thursday 3 March 2011

Visual Studio's load test and 400 Bad request errors

When trying some load testing with Visual Studio Ultimate edition. My load test received lots of 400 bad request errors. But why?

I had a look at my page that was claiming to be full of errors and it was fine. Even Fiddler reported that there were no 400's being returned from my page.

I took a look more closely at the URL that was returning the 400 and it was not the same as the one I put into the Web Performance test. It had suffixed my URL with %3C%25 - I had a look and this is URL encoding for <%. The 'start writing code' symbol in web forms pages/views.

Workaround to fix this 400 Bad Request %3C%25 problem

I routed about my View and found it could be a problem with the ad calls in the page. They make https ad calls so maybe this is the problem since I heard something about https not being supported properly in load test.

So I stripped the ad call parts out of my View and everything is working fine now.

Obviously this will now affect my page speed so not very accurate. Not impresses given the cost of Visual Studio Ultimate

Follow britishdev on Twitter