Closed Mike-E-angelo closed 3 years ago
This is something we can't fix automatically without drastically changing the infrastructure to use Roslyn. This is also that should be rather rare as all the listed cases are anti-patterns.
Workaround: Starting with 6.0.0-rc1 there is a way of achieving this by creating a class deriving from CSharpHelper
and overriding ShouldUseFullName
. Then registering the implementation as ICSharpHelper
, see Design-time services.
Thank you very much for looking into this, @AndriySvyryd!
This is also that should be rather rare as all the listed cases are anti-patterns.
Source for this, please? It would seem if that were the case, warnings would be emitted by either Roslyn or R# during design/compile time, neither of which do so.
Either way, one developer's anti-pattern is another's strong use of the .NET type system. :P
Then register the implementation as ICSharpHelper, see Design-time services.
Cool, thank you for letting me know. 👍
Source for this, please? It would seem if that were the case, warnings would be emitted by either Roslyn or R# during design/compile time, neither of which do so.
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-namespaces
❌ DO NOT give the same name to types in namespaces within a single application model. ❌ DO NOT introduce generic type names such as Element, Node, Log, and Message. ❌ DO NOT use the same name for a namespace and a type in that namespace.
I couldn't answer because comments are now closed. You can use this to get your model "size":
var model = context.Model;
Console.WriteLine("Model has:");
Console.WriteLine($" {model.GetEntityTypes().Count()} entity types");
Console.WriteLine($" {model.GetEntityTypes().SelectMany(e => e.GetDeclaredProperties()).Count()} properties");
Console.WriteLine($" {model.GetEntityTypes().SelectMany(e => e.GetDeclaredForeignKeys()).Count()} relationships");
But the benefit you get from a compiled model also depends on the shape of your model. In general if the startup time wasn't bothering you that much previously you probably won't notice a difference with a compiled model.
I appreciate you providing this information, @AndriySvyryd. I see now that you are talking guidelines and not analysis rules/warnings, which I would expect to be applied in the case of anti-patterns (although who knows).
DO NOT give the same name to types in namespaces within a single application model.
I suppose we'd have to really discern what is considered an application model here. In the case above, IdentityUser
is inheriting another IdentityUser
located in another referenced assembly. I can see the case here for not having two `IdentityUser' within the same assembly/project, but IMO that is not applicable here as an application-specific class is inheriting from a generalized framework class located in another assembly altogether.
DO NOT introduce generic type names such as Element, Node, Log, and Message.
So System.Index
violates this guideline? 🙃
DO NOT use the same name for a namespace and a type in that namespace.
Yeah, TBH I am not a fan of this one. It actually bothers me a bit. 😬 It seems both redundant and lazy. It also makes me want to rename it just by looking at it. Nonetheless, it's still technically/syntactically correct so thought it would be a good use case to report.
I couldn't answer because comments are now closed. You can use this to get your model "size":
That is very cool! Thank you very much. I was interested in seeing how many relationships are found within the # of properties.
I am in a bit of a refactor ATM (trying to un-scope my DbContext
s and replace with IDbContextFactory
), but will try to get that together and see what the results are.
Thank you for taking the time to assist. 👍
Not to be a stickler here. 😁
There's also this one, which I think better applies to Index
:
❌ DO NOT give types names that would conflict with any type in the Core namespaces.
I'm not a fan of this rule as there are SO many core namespaces/types and it's so very easy to meet a type name that already exists. Also, what happens when there's a new "Core" type that is introduced at some point later that conflicts with a type you've already created? This is the whole point of namespaces.
Along those lines, my feeling is that a lot of these guidelines are made to assist the tooling, which has been very deficient around these types of issues over the years. One of the many reasons I use ReSharper. :)
Along those lines, my feeling is that a lot of these guidelines are made to assist the tooling
They are mostly for the benefit of the ones reading the code. I'd add a more general guideline - avoid type names that will need to be namespace-qualified. But as you said these are guidelines, not rules.
They are mostly for the benefit of the ones reading the code
Nodding along, @AndriySvyryd. I appreciate the discussion and hearing your viewpoint.
FWIW my stats are as follows:
Model has:
126 entity types
451 properties
117 relationships
568 total compilation targets
So at only 568 targets, it would seem I would not benefit much from a compiled model. This aligns with my observations when attempting to utilize a compiled model from my context. This would only yield ~114ms of startup time savings, if I understand correctly.
This would only yield ~114ms of startup time savings, if I understand correctly.
This sounds about right.
Are there downsides to overriding CSharpHelper.ShouldUseFullName? Is there other generated code that's going to be wrong if we do that?
Are there downsides to overriding CSharpHelper.ShouldUseFullName?
Not really, just potentially uglier code for compiled models and migration snapshots.
Is there a way we could make it smarter, so it only applies to Optimize-DbContext?
Is there a way we could make it smarter, so it only applies to Optimize-DbContext?
No.
@AndriySvyryd I'm facing an issue where I want to use this feature, but with an existing database that I can't modify, so even if there may be some anti-patterns, it is what it is but the Optimize-DbContext generates code that doesn't compile (due to not having full names in the references). I'm not sure I would create CSharpHelper.ShouldUseFullName when calling Optimize-DbContext? IMHO it would be nice with a parameter to Optimize-DbContext that specifies that full names should be used, is that feasible?
Workaround: Starting with 6.0.0-rc1 there is a way of achieving this by creating a class deriving from CSharpHelper
Hi @AndriySvyryd I am investigating this again and cannot seem to find this class. Can you point me in the direction of where it's located?
In EFCore.Design
I see ICSharpHelper
but not CSharperHelper
. Do you have a full path and/or URL for reference @ErikEJ?
I'm now on EF Core 6.0.6 and this part works great, but there's still one issue. I have a table named DayOfWeek (which in hindsight wasn't great, but I can't change it now). The problem is that the optimized CompiledModule causes a conflict between my own data model class for DayOfWeek and System.DayOfWeek in the auto-generated file. I have to manually add this line into the file to work around the issue. It would be good if this generated file from the Optimize-DbContext would always fully-qualify all types, at least as an option if not default.
using DayOfWeek = Skumberg.DataModel.Models.DayOfWeek;
This tracks adding a simple commandline switch - https://github.com/dotnet/efcore/issues/27203
Ah, here we go: https://github.com/dotnet/efcore/blob/main/src/EFCore.Design/Design/Internal/CSharpHelper.cs
I was looking here: https://github.com/dotnet/efcore/tree/main/src/EFCore/Design/Internal
How do you reference this in the code? I am not able to find the CSharpHelper in "Microsoft.EntityFrameworkCore.Design.Internal". Am I missing something?
How do you reference this in the code? I am not able to find the CSharpHelper in "Microsoft.EntityFrameworkCore.Design.Internal". Am I missing something?
Add a reference to Microsoft.EntityFrameworkCore.Design
How do you reference this in the code? I am not able to find the CSharpHelper in "Microsoft.EntityFrameworkCore.Design.Internal". Am I missing something?
Add a reference to
Microsoft.EntityFrameworkCore.Design
Here are the references:
Here's the error:
@dharmeshtailor Did you try recompiling? If you are getting the EF1001 warning then the type is referenced correctly.
@AndriySvyryd this is what I got on recompiling. It seems reference is correct.
I have .net 7.0 class library.
@AndriySvyryd I have created a sample solution having same issue.
Oh, it's because Microsoft.EntityFrameworkCore.Design
is referenced as a build-only dependency. Edit the .csproj and replace
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
with
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5" />
@AndriySvyryd Works perfectly. Thanks. :-)
File a bug
When using
Optimize-DbContext
, the generated types are not fully qualified and/or do not fully resolve the generated type, resulting in compile errors.I have identified 3 scenarios:
IdentityUser
)System
namespace (e.g.Index
)Definition.Definition
)Include your code
I have committed a SLN with the generated compile errors here for your review: https://github.com/Mike-E-angelo/Stash/blob/master/EfCore6.Model/EfCore6.Model.sln
Include stack traces
NA
Include verbose output
Include provider and version information
EF Core version:
6.0.0-preview.7.21378.4
Database provider:Microsoft.EntityFrameworkCore.SqlServer
Target framework:net6.0
Operating system: Windows 10 IDE: Visual Studio 2022 Preview 3.0