Disable the default constructor on a Database-First workflow
Asked Answered
D

3

8

How can I prevent the use of the parameterless constructor of the generated DbContext?

var dcx = new DataEntities();

The default constructor is generated by the T4 template, and I thus cannot override it in a partial class. I would prefer it not compile, but a runtime error would also be good.

Discontinuation answered 28/7, 2014 at 9:46 Comment(0)
Q
14

You can modify the template to provide the constructor you want.

  • Open the *.Context.tt file
  • Go to line ~59
  • Change this code.

    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    
  • Into the default constructor you want, for example.

    public <#=code.Escape(container)#>(string nameOrConnectionString)
        : base(nameOrConnectionString)
    
  • Save

Qr answered 20/8, 2014 at 3:57 Comment(1)
I couldn't find *.Context.tt file in EF Core database first approach.Marvamarve
S
2

You can inherit the DbContext created by the template, define your own constructor, and use the inherited DbContext instead of the one generated by the template.

public class MyModifiedDbContext : TheTemplateGeneratedDbContext
{
   public MyModifiedDbContext() 
   {
       // define your own constructor
   }
}

Or make it private to avoid its use, so you get the error at compile time

public class MyModifiedDbContext : TheTemplateGeneratedDbContext
{
   private MyModifiedDbContext() 
   // ...
}

Use MyModifiedDbContext instead of TheTemplateGeneratedDbContext

Shagreen answered 20/8, 2014 at 8:42 Comment(4)
This doesn't prevent me from using new TheTemplateGeneratedDbContext().Discontinuation
Of course, but there are many options to "hide" the original generated DbContext. It all depends on the structure of your project files. I suppose you have a monolithic app with everything messed up, and so you don't have control on who, where and when uses this constructor. Stuck to Yuliam Chandra solution or re-organize your code.Shagreen
Would you mind elaborating on how I could implement control on who, where and when uses this constructor, and what code reorganizations I should consider?Discontinuation
You can apply architectural patterns. It cannot be explained in a few lines. But the solution is mostly based on interfaces. Then you can use DI or an abstract factory. The projects that needs the DbContext uses the DI or the abstract factory, but doesn't know anything about the final implementation. The final implementation of the DI dependency, or the abstract factory is the only one with acces to the implementation of the DbContexts. It0s much better to have the things under control, that to "make a trick" to avoid the developer from doing the wrong thing.Shagreen
V
1

I gave up waiting for EF Core team to add this as an option. I don't want to make and maintain my own T4 templates for this - that's nuts!

Solution for me was just to run some regex on the generated code as part of a powershell script.

fix-dbcontext.ps1

$filename=$args[0]

# load context file
$content = (Get-Content -Raw $filename) 

[regex] $commentOutConstructorRegex = '(?ms)(?<=: DbContext\s*.*?)(public.*?)(?=\s*public)'
$content = $commentOutConstructorRegex.Replace($content, '// Default constructor removed', 1)

[regex] $removeOnConfiguringRegex = '(?ms)(protected override void OnConfiguring).*?(?=\s*protected)'
$content = $removeOnConfiguringRegex.Replace($content, '// Generated OnConfiguring removed', 1)

[regex] $dateCommentRegex = '(?ms)(?=\s*public partial class)'
$content = $dateCommentRegex.Replace($content, "`r`n`t// Generated " + (Get-Date).ToString() + "`r`n", 1)

$content | Out-File -Encoding UTF8 $filename

This will:

  1. Remove the default constructor
  2. Remove the OnConfiguring method including hardcoded connection string
  3. Add the date in a comment

Just run it with .\fix-dbcontext.ps1 .\MyDBContext.cs.

You probably want to change that last line to context.txt instead of $filename until you're sure it does what you want.

IMPORTANT: This was tested only on EFCore templates, but if you understand my Regexes you should be able to modify it for EntityFramework if it doesn't already work.

Valerlan answered 22/2, 2021 at 20:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.