How to set default values for string properties without having them overridden by our initialising code

Like many, our database has rather a lot of naughty nullable columns that really should be non-nullable, so we end up with null data issues all over the place. One way to avoid this is to modify the property in the .edmx file to add a default value. However, this is slow and painful, and easy to forget.

As there is no use case we can foresee where you would want a null string property, we have taken the step of adding a constructor to the entity (generated in the T4 template) that initialises every string property to an empty string. This means that whenever you create a new entity, any string properties will be initialised, avoiding any null values.

However, this leaves you with a problem if you want to set a (non-empty) default value for a string.

Now I should point out that in over ten years of development, we’ve never actually done this, but as there is always the remote possibility that someone would want to do it, I wanted to add code to allow it.

Modifying the .tt file was a bit painful, but I ended up adding the following just inside the code that creates the opening line of the class…

    public <#=code.Escape(entity)#>() {
<# foreach (EdmProperty p in entity.Properties.Where(ep => code.Escape(ep.TypeUsage) == "string")) {
    #>
      <#=code.Escape(p)#> = "";
    <# } #>
      PostCtor();
    }

    partial void PostCtor();

The indentation is all over the place as editing .tt files is messy, and what is generated doesn’t always seem to line up with what you type. However, as this code is unlikely to be read, and it works, the indentation isn’t a huge issue.

If you look in the generated code for an entity (City in this case), you’ll see that we now have a ctor that initialises the string properties, and we also have a partial method wittily named PostCtor() which is called from the constructor after the initialisation (hence the witty name)…

public City() {
 Name = "";
 PostCtor();
}
 
partial void PostCtor();

Now, if you want to set a default value for a string property, create a file named (in this case) CityExt.cs, change the class name to be just City and make it partial, then call PostCtor() with the code you want. For example, if you wanted all cities to have a default name of “Jim” (and why not, Jim is a perfectly fine name for a city), your code would look like this…

partial void PostCtor() { 
  Name = "Jim";
}

If you don’t call PostCtor(), then the call will be compiled out of the entity, so there isn’t any overhead with this.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *