问题
I have done scaffolding of my SQLServer database. And it creates the POCO objects in the specified folder. What i would like to do is that it extends from my base class. I also use repository pattern so i need to have Id key on every entity and I don't want to change that each time i rescaffold the database.
Scaffold Model Example
public partial class Food
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
}
Expected Result:
public partial class Food : EntityBase
{
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
}
public class EntityBase : IEntityBase
{
public int Id { get; set; }
}
回答1:
You can use DbContextWriter & EntityTypeWriter to customize scaffold output.
In newer versions of entity core writers renamed:
- DBContextWriter ==>> CSharpDbContextGenerator
- EntityTypeWriter ==>> CSharpEntityTypeGenerator
Write some custom type writer, you can override everything and you will get your own code generator:
//HERE YOU CAN CHANGE THE WAY TYPES ARE GENERATED AND YOU CAN ADD INTERFACE OR BASE CLASS AS PARENT.
public class CustomEntitiyTypeWriter : EntityTypeWriter
{
public CustomEntitiyTypeWriter([NotNull] CSharpUtilities cSharpUtilities)
: base(cSharpUtilities)
{ }
// Write Code returns generated code for class and you can raplec it with your base class
public override string WriteCode([NotNull] EntityConfiguration entityConfiguration)
{
var classStr = base.WriteCode(entityConfiguration);
var defaultStr = "public partial class " + entityConfiguration.EntityType.Name;
var baseStr = "public partial class " + entityConfiguration.EntityType.Name + " : EntityBase";
classStr = classStr.Replace(defaultStr, baseStr);
return classStr;
}
}
declare it in setup:
public static void ConfigureDesignTimeServices(IServiceCollection services)
=> services.AddSingleton<EntityTypeWriter, CustomEntitiyTypeWriter>();
and then scaffold db, you can do the same for DBContext with CustomDBContextWriter.
回答2:
@Tornike Choladze's excellent answer led me in the right direction, but in the latest versions of .Net Core (2.0 >) this has to be done a little differently it seems, with regard to the setup.
The custom entity type generator:
class MyEntityTypeGenerator : CSharpEntityTypeGenerator
{
public MyEntityTypeGenerator(ICSharpUtilities cSharpUtilities) : base(cSharpUtilities) { }
public override string WriteCode(IEntityType entityType, string @namespace, bool useDataAnnotations)
{
string code = base.WriteCode(entityType, @namespace, useDataAnnotations);
var oldString = "public partial class " + entityType.Name;
var newString = "public partial class " + entityType.Name + " : EntityBase";
return code.Replace(oldString, newString);
}
}
And the setup, which consists of a class in the same assembly and implementing IDesignTimeServices
:
public class MyDesignTimeServices : IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<ICSharpEntityTypeGenerator, MyEntityTypeGenerator>();
}
}
回答3:
Currently, the scaffolding tools do not support the scenario you describe. There are no options to customise their output, only the location of the generated files and whether to use Fluent API or data annotations for configuration.
EF Core is a Code First framework. The advice is that once you have reverse-engineered your model from the existing database, you use migrations to keep the two in sync with each other from then on.
Having said that, I realise that might not always be possible depending on how responsibilities are apportioned within teams. In that kind of case, you might want to consider opening an issue requesting this feature on the GitHub repo for EF Core: https://github.com/aspnet/EntityFramework.
回答4:
In case you want to modify entity names (and file and class names) here's something that might help:
Based on Chris Peacock's answer (and comments) you can build two classes to modify the names of entities and files (this works in Core 2.2).
public class CustomEFUtilities : CSharpUtilities
{
public override string Uniquifier(
string proposedIdentifier, ICollection<string> existingIdentifiers)
{
var finalIdentifier = base.Uniquifier(proposedIdentifier, existingIdentifiers);
// your changes here
if (finalIdentifier.StartsWith("tl"))
{
finalIdentifier = finalIdentifier.Substring(2);
}
return finalIdentifier;
}
}
And similarly:
public class CustomEFDesignTimeServices : IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<ICSharpUtilities, CustomEFUtilities>();
}
}
来源:https://stackoverflow.com/questions/40728223/entity-framework-core-customize-scaffolding