Reputation: 2417
Context:
I use Database-first approach to generate my entities with Entity Framework Core and with use of Scaffolding. Each time I change something in the database I run Scaffolding with -f
parameter to rewrite generated entities. So far so good. In my database schema I have a few Lookup tables that serve the purpose as Enums for my other tables and those other tables has Foreign key on them.
Problem:
I would like to generate from these lookup tables Enums which I can use in my code. These enums should be populated by the data in the lookup table (Id, Value). Is something like this even possible ?
I saw that one can ignore those tables from Entity generation and link their own enums with use of value-conversions. But is this really the only way around ?
Example of my database schema:
TABLE: Category
Id | Value |
---|---|
0 | Cardio |
1 | Strength |
2 | Hyperthrophy |
TABLE: Exercise
Id | Name | Category |
---|---|---|
0 | Deadlift | 1 |
1 | Benchpress | 1 |
2 | Jogging | 0 |
So from table Category
I would like to generate simple Enum:
public enum Category {
Cardio = 0,
Strength = 1,
Hyperthrophy = 2
}
and then I want it to be used in the entity Exercise
like:
public partial class Exercise {
public Exercise() {
}
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
Upvotes: 5
Views: 2006
Reputation: 2367
It's not impossible, but you need to know if it's worth it. I develop using database-first, so to generate my entities I always run the scaffold tool. When I needed to customize my entities, I overrode a method that the tool uses to generate the files.
See:
[SuppressMessage("Usage", "EF1001:Internal EF Core API usage.", Justification = "<Pending>")]
public class EntityTypeGenerator : CSharpEntityTypeGenerator
{
public EntityTypeGenerator([NotNull] IAnnotationCodeGenerator annotationCodeGenerator,
[NotNull] ICSharpHelper cSharpHelper) :
base(annotationCodeGenerator, cSharpHelper)
{
}
public override string WriteCode(IEntityType entityType,
string @namespace,
bool useDataAnnotations,
bool useNullableReferenceTypes)
{
var code = base.WriteCode(entityType, @namespace,
useDataAnnotations, useNullableReferenceTypes);
var oldString = "public partial class " + entityType.Name;
var newString = "public partial class " + entityType.Name + ":
Repositories.Infra.EntityBase";
var newCode = code.Replace(oldString, newString);
if (entityType.Name == "Task")
{
oldString = "byte StatusId ";
newString = "Business.Models.Tarefas.EnumStatusTask StatusId ";
newCode = code.Replace(oldString, newString);
}
return newCode;
}
}
For this to work I created a separate project just for the purpose of affecting entity generation. In it I referenced the library Microsoft.EntityFrameworkCore.Design.
I injected my generator class inside the DesignTimeServices class implementation
public class DesignTimeServices: IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<ICSharpEntityTypeGenerator, EntityTypeGenerator>();
}
}
In the main project (the runtime one, in this case the API), I referenced my new project and added the reference to the lib Microsoft.EntityFrameworkCore.Tools
The following link can serve as a basis for understanding how it works and what you can do https://learn.microsoft.com/en-us/ef/core/cli/services
Upvotes: 0
Reputation: 11291
While this is theoretically possible to generate code based on any data, there is no tool I know of what can do what you ask at this moment.
But the real question is: why would you want this? Or better is this really wat you want?
Scaffolding is based on the database scheme, not on the table contents. The table data is and should be assumed to be dynamic. Else (i.e. if the data is static) you should question why you put it in the database at all: you could and should just put it in the code. An enum is a rather static structure.
Entity Framework is an object mapper for a relational database. So you should just use the dynamic relationships and thus the key coupling.
Upvotes: 1