-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RevEng: Use ScaffoldingTypeMapper #8626
Conversation
5098a10
to
7d4e1f0
Compare
893015e
to
a4c225e
Compare
@@ -9,11 +9,11 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding | |||
{ | |||
public class TypeScaffoldingInfo | |||
{ | |||
public TypeScaffoldingInfo([NotNull] Type clrType, bool inferred, bool? scaffoldUnicode, int? scaffoldMaxLength) | |||
public TypeScaffoldingInfo([NotNull] Type clrType, bool isInferred, bool? scaffoldUnicode, int? scaffoldMaxLength) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is prefixes are discouraged on parameters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git inability to detect file move & broken resharper. I changed it to something else and forgot original name. I will remove is in parameter.
|
||
var dataType = underlyingDataType ?? (columnModel.DataType + (columnModel.MaxLength.HasValue ? $"({columnModel.MaxLength.Value})" : "")); | ||
|
||
var typeScaffoldingInfo = _scaffoldingTypeMapper.FindMapping(dataType, keyOrIndex: false, rowVersion: columnModel.DataType == "timestamp"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this to be correct we have to know whether the property is part of a key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At present, ReverseEngineer does not flow enough information to put here directly. This is not correct. (same goes for keyOrIndex being passed as false always). I can set this one as false too for now. We can decide later how to flow the information about key/index/rowversion from database model & make this call accurate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with postponing it. Please don't close the issue until it is fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to false.
@@ -457,8 +450,7 @@ namespace E2ETest.Namespace | |||
|
|||
modelBuilder.Entity<OneToOneSeparateFkprincipal>(entity => | |||
{ | |||
entity.HasKey(e => new { e.OneToOneSeparateFkprincipalId1, e.OneToOneSeparateFkprincipalId2 }) | |||
.HasName("PK_OneToOneSeparateFKPrincipal"); | |||
entity.HasKey(e => new { e.OneToOneSeparateFkprincipalId1, e.OneToOneSeparateFkprincipalId2 }); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why has the HasName() call disappeared? Where is the name being stored now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name is same as default name. It was a bug to scaffold them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, but I would like to have at least one test where we do generate it because it is different from the default. Can we arrange that somehow (e.g. rename a PK or two in the E2E.sql file)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comment #8594 (comment)
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public class DbContextScaffolder | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the name of this class confusing as, if I understand correctly, it is responsible for scaffolding all the code, not just the DbContext?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am happy with better name if there is any. This class is an orchestrator to our scaffolding.
I have aligned the name with our command names. While this class is scaffolding all the code not just the DbContext, same way all the code is scaffolded even though we call the command Scaffold-DbContext
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about ScaffoldingOrchestrator
or ScaffoldingController
then? (I didn't like Scaffold-DbContext
for the same reason).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bricelam @ajcvickers - Name suggestions? I am fine with any name. as long as it conveys meaning.
Afaik, migrations have MigrationScaffolder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My two cents:
- Consider the word "model" to convey both the
DbContext
and the types - Not sure this is comparable to
MigrationsScaffolder
. At first glance it looks like that one is doing more of the work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MigrationScaffolder
adds a new migration. (actual runner of Add-Migration
) is it something different @bricelam ?
ModelScaffolder
sounds good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ModelScaffolder sounds good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add-Migration code basically looks like this:
// Generate the code
var migraton = migrationsScaffolder.ScaffoldMigration(name, namespace)
// Write the files
return migrationsScaffolder.Save(migration, directory)
+1 for ModelScaffolder
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
</data> | ||
<data name="RootNamespaceRequired" xml:space="preserve"> | ||
<value>Root namespace of the project is required to generate code.</value> | ||
</data> | ||
<data name="MigrationsAssemblyMismatch" xml:space="preserve"> | ||
<value>Your target project '{assembly}' doesn't match your migrations assembly '{migrationsAssembly}'. Either change your target project or change your migrations assembly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re the deletions above, what error message do users see if they fail to set these things (or e.g. set them to non-existent paths) now? We spent a bit of time making sure the error messages were useful...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were removed in other PR which was already approved.
As explanation,
In current codebase, above messages are thrown from ReverseEngineerConfiguration.CheckValidity()
(I am talking about namespace/project dir/connectionstring).
We create RevEngConfig object in this class https://github.com/aspnet/EntityFramework/blob/dev/src/EFCore.Design/Design/Internal/DatabaseOperations.cs
Based on the annotations in the class, none of those properties will ever be null. If they will be then we will throw long before we reach at validation check.
The only way to get those exception is user passing invalid Config object in ReverseEngineerGenerator.GenerateAsync function. But we have removed the config object and added those properties as parameter. So for our normal UX from PMC/cmd, the values will be proper. The only way exceptions will arise is when user explicitly pass null to parameters marked as not-null and I believe it is fine to just throw argument null exception in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Have a check what happens if you fail to enter/enter bad info at the command-line. If the error you get back is sufficient to help the user figure out what's wrong and fix it then so be it. But if they just get some generic error that's along the lines of "something went wrong" then we really tried to be more useful than that with the error messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked codebase.
RootNameSpace -> we take from command line if passed else it will be same as AssemblyFileName of the assembly
ProjectDirectory -> Use command line arg or take the current directory
So we will never have incorrect values for above unless passed wrong by user.
@bricelam can tell what would we throw because it is not specific to scaffolding but rather any EF command.
ConnectionString is required arg in scaffold command, if user don't provider it then we show error as it is required arg missing. which is self-explanatory.
7d4e1f0
to
999e005
Compare
Updated PR after going through rebase hell. The real commit is this PR is much smaller. (thanks to nice design of ScaffoldingTypeMapper by @ajcvickers ). It is not accurate in terms of scaffolded code yet. But this defines a layer what ScaffoldingTypeMapper is supposed to do & how it will work.
|
eb3d7ab
to
44dc5f4
Compare
@@ -23,6 +23,7 @@ public virtual void ConfigureDesignTimeServices(IServiceCollection serviceCollec | |||
=> serviceCollection | |||
.AddSingleton<IRelationalTypeMapper, SqliteTypeMapper>() | |||
.AddSingleton<IDatabaseModelFactory, SqliteDatabaseModelFactory>() | |||
.AddSingleton<IScaffoldingHelper, SqliteScaffoldingHelper>(); | |||
.AddSingleton<IScaffoldingHelper, SqliteScaffoldingHelper>() | |||
.AddSingleton<ScaffoldingTypeMapper>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should only need to replace "core" design-time services in the provider, not re-add them.
4fca8de
to
f565d06
Compare
44dc5f4
to
8772ea8
Compare
8772ea8
to
2b689bb
Compare
No description provided.