Open tonysneed opened 2 years ago
Transfer https://github.com/TrackableEntities/EntityFrameworkCore.Scaffolding.Handlebars/issues/188#issuecomment-994884840 to this issue.
I am now looking at the second part of my request and wanted to clarify why I wanted it. When I was writing the design time transformer class I created a JSON lookup file for my mappings:-
"Name": "EntitiesOne:Aircraft",
"NameOverride": "MyAircraft",
"Mappings": [
{
"Name": "Livery",
"NameMapping": "MyLivery"
}
]
To correctly select the mappings:-
Entity Name Mappings require the context:entityname PropertyName Mappings require context:entityname:propertyname So I need context and so I need the TransformContextFileName method to be called early on in my Transformer class so I can store the context locally. Currently it is only called when the model is generated in the HbsCSharpModelGenerator. Hope this makes sense.
@gpender I am trying to wrap my head around why you need to call ContextTransformationService.TransformContextFileName
in the WriteCode
method of HbsCSharpDbContextGenerator
and how this would enable you to access the transformed context file name in your transformer class.
Perhaps you would be kind enough to create a small repo containing an example transformer class that shows how calling ContextTransformationService.TransformContextFileName
in HbsCSharpDbContextGenerator
surfaces the context file name so that you can use it in your other transform methods?
Hi @tonysneed and Happy New Year :) sorry for not getting back to you sooner. In our Use Case application we have multiple existing SQLSERVER databases which we are migrating and there are tables with duplicate names.
So for example we have the table Aircraft appearing in 2 databases (The Aircraft tables are both different) DatabaseA with table Aircraft DatabaseB with table Aircraft
To scaffold the entities correctly I would like to have a single mappings.json lookup file where we have all the mappings for all databases:-
[
{
"Name": "DatabaseA:Aircraft",
"NameOverride": "CivilianAircraft",
"Mappings": [
{
"Name": "Tail",
"NameMapping": "TailLivery"
}
]
},
{
"Name": "DatabaseB:Aircraft",
"Mappings": [
{
"Name": "Type",
"NameMapping": "AircraftType"
}
]
}
]
My transformer class uses this single json file to make the transforms and needs the current context (database) to fully qualify the entries.
In the code below you can see that I store the _context locally when it is called and then use it to access the entries in the mappings.json file. I hope this makes sense :)
namespace HandlebarsScaffolding
{
public class ScaffoldingDesignTimeServices : IDesignTimeServices
{
private string _entityName, _context;
private readonly EntityMappings _mappings;
public ScaffoldingDesignTimeServices()
{
try
{
_mappings = File.ReadAllText($@"{Environment.CurrentDirectory}\Mapping\mappings.json").FromJson<EntityMappings>();
Console.WriteLine($@"Reading {Environment.CurrentDirectory}\Mapping\mappings.json");
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
public void ConfigureDesignTimeServices(IServiceCollection services)
{
services.AddHandlebarsScaffolding(options);
services.AddHandlebarsTransformers(
contextFileNameTransformer: (c) =>
{
_context = Path.GetFileNameWithoutExtension(c);
return c;
},
entityNameTransformer: MapEntityName,
constructorTransformer: MapPropertyInfo,
propertyTransformer: MapPropertyInfo,
navPropertyTransformer: MapNavPropertyInfo,
entityFileNameTransformer: MapEntityName);
}
private string MapEntityName(string entityName)
{
_entityName = entityName;
var nameOverride = _mappings.FirstOrDefault(e => e.Name == $"{_context}:{_entityName}")?.NameOverride;
return nameOverride ?? entityName;
}
private EntityPropertyInfo MapNavPropertyInfo(EntityPropertyInfo e)
{
return new EntityPropertyInfo(MapPropertyTypeName(e.PropertyType), MapPropertyName(e.PropertyName, false));
}
private EntityPropertyInfo MapPropertyInfo(EntityPropertyInfo e)
{
return new EntityPropertyInfo(MapPropertyTypeName(e.PropertyType), MapPropertyName(e.PropertyName));
}
private string MapPropertyTypeName(string propertyTypeName)
{
var propertyTypeNameOverride = _mappings.FirstOrDefault(e => e.Name == $"{_context}:{propertyTypeName}")?.NameOverride;
return propertyTypeNameOverride ?? propertyTypeName;
}
private string MapPropertyName(string propertyName, bool useEntityNameFilter = true)
{
IEnumerable<Mapping> entityMappings = null;
if (useEntityNameFilter)
entityMappings = _mappings.Where(m => m.Name == $"{_context}:{_entityName}").SelectMany(m => m.Mappings);
else
entityMappings = _mappings.Where(m=>m.Name.Split(':')[0] == _context).SelectMany(m => m.Mappings);
var map = entityMappings.FirstOrDefault(m => m.Name == propertyName);
return map != null ? map.NameMapping : propertyName;
}
}
}
Been super busy, but I haven’t forgotten about this. Thanks for patience and please stay tuned.
Add
IContextTransformationService
toHbsCSharpDbContextGenerator
so that the context can be made available when using the other transforms: