Overriding code-generated DbContext constructor
Solution 1
The best I can suggest is a factory method:
private HOLDbEntities(string contextName) : base(contextName) { }
public static HOLDbEntities Create() {
return new HOLDbEntities(ContextName);
}
and use HOLDbEntities.Create()
rather than new HOLDbEntities()
.
Solution 2
I up-voted the previous accepted answer because it is a fairly elegant way of doing it. However another approach would be to modify the T4 template that generates the dbContext Class.
When using EF DB first you have a .edmx file and under that you have an [Entity].Context.tt file. Go into that file and remove (or modify) the following code:
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
}
foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
{
// Note: the DbSet members are defined below such that the getter and
// setter always have the same accessibility as the DbSet definition
if (Accessibility.ForReadOnlyProperty(entitySet) != "public")
{
#>
<#=codeStringGenerator.DbSetInitializer(entitySet)#>
<#
}
}
#>
now your context class will generate without a constructor, so you should be able to go and create one in an extended class.
Solution 3
i changed the context.tt as follows:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
}
foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
{
// Note: the DbSet members are defined below such that the getter and
// setter always have the same accessibility as the DbSet definition
if (Accessibility.ForReadOnlyProperty(entitySet) != "public")
{
#>
<#=codeStringGenerator.DbSetInitializer(entitySet)#>
<#
}
}
#>
var Method = (typeof(Entities)).GetMethods(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).FirstOrDefault(x => x.Name == "OnModelConstructed");
if (Method!=null) Method.Invoke(this,null);
}
so i can declare a OnModelConstructed method in a partial class of the context.
Chris Dixon
I'm a Senior Programmer specialising in .NET Core (C#), JavaScript (Vanilla/MVVM) and surrounding technologies. LinkedIn: https://www.linkedin.com/in/chris-dixon-69938829
Updated on June 05, 2022Comments
-
Chris Dixon about 2 years
I'm sure I've done this before at some stage, but I can't figure out how to now! My scenario:
// This is generated from EDMX public partial class HOLDbEntities : DbContext { public HOLDbEntities() : base("name=HOLDbEntities") { } }
Now, I want this connection string to be easily changeable (I want to Implement from the HOLDbEntities), so I need to override this constructor.
I've tried:
public partial class HOLDbEntities { private const string _contextName = "HOLDbEntities"; public static string ContextName { get { return _contextName; } } public HOLDbEntities() : base(ContextName) { } }
But this throw an error:
HOLDbEntities already defines a member called "HOLDbEntities" with the same parameter types.
I can understand why this errors, but how would I stop the constructor being auto-generated in the first place in order to do what I'm trying to achieve?
-
Chris Dixon over 11 yearsThis seems very elegant to what I'm trying to achieve, I'll give it a shot now and see if it works!
-
Chris Dixon over 11 yearsWorks fine, but Unity is now complaining that the context cannot be constructed with a String value. Any way around this? Your answer is correct for my scenario anyway.
-
alamin over 8 yearsin MSDN it says DbContext constructor overriding with a string Constructs a new context instance using the given string as the name or connection string for the database to which a connection will be made. - can you please you explain it to me clearly or give me an example or reference. i did not find any good result while searching for it :(
-
as9876 over 8 yearsWon't the T4 code also get regenerated if you, say, drag another table onto the designer?
-
Dylan Hayes about 8 years@AvrahamSeff nope, the t4s stay the same, and generate .cs files. any changes to the .cs files would get overrwitten in the way that you describe, but this is a change to the file that is doing the generating.
-
Admin over 7 years@as9876 the T4 code includes generic code that iterates over the entity types, so it doesn't need to be regenerated when new entity types are added
-
Jonathan Wood over 6 yearsIf you're going to edit the T4 template, then why not just modify the constructor there instead of removing it and adding another partial class?