Rewiring

Hardening property access with EF Core Power Tools

When using EF Core Power Tools (which you should if you're doing DB first on EF Core, it generates everything with public get and set by default.

I've been trying to make my domain models less anemic and more secure, so I wanted to change this to:

Luckily EFPT provides customization options via T4 templating, so it's a pretty straightforward change once you know what to tweak.

Here's how to get started using the CLI.

  1. In efcpt.config.json, in code-generation, set either use-t4 or use-t4-split to true.
  2. Run the reverse engineering dotnet efcpt "<connectionstring>" postgres
  3. Open the newly generated EntityType.t4

Here's the relevant modifications:

    foreach (var property in EntityType.GetProperties().OrderBy(p => p.GetColumnOrder() ?? -1))
    {
        ...
        //1. set the setter as internal
    public <#= code.Reference(property.ClrType) #><#= needsNullable ? "?" : "" #> <#= property.Name #> { get; internal set; }<#= needsInitializer ? " = null!;" : "" #>
<#
    }

    foreach (var navigation in EntityType.GetNavigations())
    {
        //helper for the backing field name
        var privateName = navigation.Name.Substring(0, 1).ToLower() + navigation.Name.Substring(1);
        ...
        //2. for collections create a private backing field and change the type to IReadOnlyCollection
        private List<<#= targetType #>> _<#= privateName #> = new List<<#= targetType #>>();
        public virtual IReadOnlyCollection<<#= targetType #>> <#= navigation.Name #> => _<#= privateName #>;
    }
    ...
    //3. create an empty private constructor
    private <#= EntityType.Name #>(){ }
}

Full samples

Key points:

This makes for a good base for building your own functionality on top of the database model and it's very easy to get going. Big thanks to EFPT once again!

Thoughts, comments? Send me an email!

#efcore #tech