find a location for property in a new city

Friday 28 January 2011

Caching. Absolute expiration or Sliding scale expiration?

You can set a cache with a temporal expiration in one of two ways:

Absolute expiration

This mean you set a time in the future in which it will expire e.g. DateTime.Now.AddMinutes(5). So the cache will remove the object from memory at that particular time in the future.

Sliding scale expiration

This means you set a length of time that the cache should keep the object in memory for from the last time it was accessed e.g. new TimeSpan(0, 0, 5, 0). That is 5 mins. So the object will be removed from cache if it hasn’t been accessed for 5mins or more.

Which temporal caching method to use?

I believe Absolute expiration is the one to use for most web page cases, unless there is a good reason not to. Imagine you are using a 5 minute sliding scale cache expiration on a popular page that gets say 50 hits/sec, chances are that this object will never expire from the cache.

How long to cache for?

Also avoiding huge expirations of hours or days on not outrageously expensive data would be an idea too. Although the benefits of large expirations are that you have to retrieve the data less often I think that reducing it from 50*60*5 = 15000 requests/5mins down to 1 request/5mins is efficient enough, without suffering from stagnant data.

Obviously, the length of how long to set your expiration for and your method of expiration is will depend on how expensive your data is and possibly other specific requirements but hopefully you can now make a more informed decision.

Follow britishdev on Twitter

Tuesday 11 January 2011

Optimising Entity Framework - Don’t query from base entity

Be careful to query the derived type when dealing with an entity data model that involves inheritance. You can massively reduce query complexity by making sure you avoid querying the base type of your model.

Say there is a model with a base type of Person and three derived types of Customer, StaffMember, Client. It doesn't matter if your inheritance model is Table per Inheritance or Table per Type (TPT) but say for example it is Table per Hierarchy (TPH) and the condition for Customer is that an OrdersID column is not null. Also say there is a quality that of all Customers that they will have a guaranteed value of PersonType == 1.

So what is the difference between:

context.People.Where(p => p.MessageType == 1) and context.People.OfType()?

Aside from the better code the difference in generated SQL is massive. For some reason Entity Framework will generate SQL that works out which derived type each of the rows in the Person table are even though I'm asking for just the base type. This means unnecessarily joining on a number of tables if you’re using TPT or evaluating many conditional columns if you’re using TPH.

I tried the different approaches on quite a large Entity Data Model of mine. There is one base type with 5 derived types and a few other entities being included (joined). Using the first query from above the generated query was 28224 characters long. The revised query was 14177. That's half the size!

Using query length is a poor way of evaluating a query because most of EF queries are explicit query lengths which don’t actually add to complexity but believe me – in the case the saving of query length was almost exclusively down to removing pointless complexity.

Follow britishdev on Twitter

Thursday 6 January 2011

Enable assembly bind failure logging using Fusion

I got a FileNotFoundException with an error message of 'Could not load file or assembly 'LoveMoneyHttpModules' or one of its dependencies. The system cannot find the file specified.' This doesn't help much but does give some advice on enabling assembly bind failure logging.

The advice is to turn on the assembly bind failure logging but gives a tip of setting the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.

That's not very friendly advice so the question is how to do that exactly. I found a nicer way to do it than messing with the registry. First, you need to open the Fusion Log Viewer tool. You can do this by opening a Visual Studio command prompt and running fuslogvw.exe or alternatively just type Fusion Log Viewer into your Windows search bar thing.
  1. Open Fusion Log Viewer
  2. Click 'Settings...' and select the 'Log in exception text' radio button. Click 'OK'
  3. Do an IISreset.
The IIS isn't meant to be part of it I just found that it wasn't working until I tried that too. Anyway, after that I started getting logs of the attempts at binding in my yellow screen of death.

Follow britishdev on Twitter

Tuesday 4 January 2011

How to POST to REST WCF web services with Fiddler

After making a set of REST web services with WCF I tested them by making requests with a browser. This is fine for GET requests however you will need some HTTP building tool such as Fiddler to test a POST, PUT or DELETE REST web service.

To begin with I have a WCF REST web service that intends for a Comment object to be POSTed:
[WebInvoke(UriTemplate = "comment", Method = "POST",
  RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
public Comment Comment(Comment comment)
    return comment;

The definition of Comment is simple:
[DataContract(Namespace = "")]
public class Comment
    public string Body { get; set; }

Note this namespace is very important as it will need to be specified in the XML sent in the request. Personally I set my DataContract with no namespace to save having to write it out in the XML every time.

Now open up Fiddler and lets get testing:

Create a POST to your REST service in Fiddler

  1. Go to the Request Builder tab in Fiddler.
  2. Set the verb to POST
  3. Set the URL to the one of your service
  4. Type "Content-Type: application/xml" into the Request Headers. (This is the bit that got be stumped for hours)
  5. Add your XML to the Request Body like <Comment><Body>colin</Body></Comment>

If you did give your DataContract a namespace other than blank as I did you will need to specify it in the XML of your Request Body. Such as: <Comment xmlns="MyNameSpace"><Body>colin</Body></Comment>

Happy testing!

Follow britishdev on Twitter