I have an edmx file in my Visual Studio project, when you insert a table from from your model into the edmx, it gets the same name as in the Database, for example, by importing myTable
you get an entity called myTable
with Set Name myTables
.
How can I make the tables adhere to a custom naming convention when adding them to my file? So, for example, adding myTable
results in an entity called tblmyTable
with Set Name tblmyTables
.
The DbContext class has a method called OnModelCreating that takes an instance of ModelBuilder as a parameter. This method is called by the framework when your context is first created to build the model and its mappings in memory.
Primary Key Convention Code First infers that a property is a primary key if a property on a class is named “ID” (not case sensitive), or the class name followed by "ID". If the type of the primary key property is numeric or GUID it will be configured as an identity column.
The default schema that EF Core uses to create database objects is dbo .
There are two types of Entities in Entity Framework: POCO Entities and Dynamic Proxy Entities.
You need to modify the <YourModelName>.tt
file in multiple places.
The template calls container.BaseEntitySets.OfType<EntitySet>()
to get all your entity sets where the returned EntityeSet.ElementType
(Where the type of ElementType
is EntityType
) contains the information about your entities.
These objects are used in many places in the template so the easiest solution would be to set the Name
property of the EntityType
. However the Name
property is internal so you need to use refection to set it.
So locate the following line in your template around line 163:
region.Begin(CodeGenerationTools.GetResourceString("Template_RegionObjectSetProperties"));
foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>())
{
And you need to add here the following code to set the Name
property:
region.Begin(CodeGenerationTools.GetResourceString("Template_RegionObjectSetProperties"));
foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>())
{
set.ElementType.GetType()
.GetProperty("Name",
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.SetProperty)
.SetValue(set.ElementType, "tbl" + set.ElementType.Name, null);
Sadly you are not done yet because you still have to change two places:
First the generated property names are not fixed so you need to locate the following line around line line 173:
<#=code.SpaceAfter(NewModifier(set))#><#=Accessibility.ForReadOnlyProperty(set)#> ObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> <#=code.Escape(set)#>
And change it to (Add the tbl
before <#=code.Escape(set)#>
:
<#=code.SpaceAfter(NewModifier(set))#><#=Accessibility.ForReadOnlyProperty(set)#> ObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> tbl<#=code.Escape(set)#>
Because of the reflection hack you need to remove the "tbl" prefix form the generated EdmEntityTypeAttribute
so you need to locate the following line around line 295:
[EdmEntityTypeAttribute(NamespaceName="<#=entity.NamespaceName#>", Name="<#=entity.Name#>")]
And change it to:
[EdmEntityTypeAttribute(NamespaceName="<#=entity.NamespaceName#>", Name="<#=entity.Name.Replace("tbl","")#>")]
You need to modify the tt
files to apply your custom naming convention.
First you should modify the <YourEdmxName>.tt
file:
Around line 23 you should locate the following method call:
fileManager.StartNewFile(entity.Name + ".cs");
This method crates your entity classes so if you want to modify the generated file names you need to change it to:
fileManager.StartNewFile("tbl" + entity.Name + ".cs");
Then around line 307 you need to find the following method declaration:
public string EntityClassOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
}
This methods writes your class names so here you need to change it to apply your convention:
public string EntityClassOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
"tbl" + _code.Escape(entity), // add tbl prefix before the entity name
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
}
Finally you need to modify your <YourEdmxName>.Context.tt
:
Around line 296 you need to locate the following method which write out the DbSet
properties:
public string DbSet(EntitySet entitySet)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} DbSet<{1}> {2} {{ get; set; }}",
Accessibility.ForReadOnlyProperty(entitySet),
_typeMapper.GetTypeName(entitySet.ElementType),
_code.Escape(entitySet));
}
And change it again to apply your convention:
public string DbSet(EntitySet entitySet)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} DbSet<{1}> {2} {{ get; set; }}",
Accessibility.ForReadOnlyProperty(entitySet),
// add "tbl" to the type name DbSet<Table> -> DbSet<tblTable>
"tbl" + _typeMapper.GetTypeName(entitySet.ElementType),
// add "tbl" to property name Tables -> tblTables
"tbl" + _code.Escape(entitySet));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With