From 32aa2066a8022f9b0f257092ecfd7e74958b60bd Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Wed, 23 Aug 2023 10:41:48 -0700 Subject: [PATCH] Document the design-time tools architecture Part of #1920 --- .../internals/diagrams/generate.cmd | 2 + .../internals/diagrams/tools-cli.mmd | 3 + .../internals/diagrams/tools-cli.png | Bin 0 -> 5348 bytes .../internals/diagrams/tools-overview.mmd | 4 + .../internals/diagrams/tools-overview.png | Bin 0 -> 5885 bytes .../internals/diagrams/tools-pmc.mmd | 4 + .../internals/diagrams/tools-pmc.png | Bin 0 -> 6498 bytes .../core/miscellaneous/internals/index.md | 30 ++++ .../core/miscellaneous/internals/tools.md | 132 ++++++++++++++++++ entity-framework/toc.yml | 7 + 10 files changed, 182 insertions(+) create mode 100644 entity-framework/core/miscellaneous/internals/diagrams/generate.cmd create mode 100644 entity-framework/core/miscellaneous/internals/diagrams/tools-cli.mmd create mode 100644 entity-framework/core/miscellaneous/internals/diagrams/tools-cli.png create mode 100644 entity-framework/core/miscellaneous/internals/diagrams/tools-overview.mmd create mode 100644 entity-framework/core/miscellaneous/internals/diagrams/tools-overview.png create mode 100644 entity-framework/core/miscellaneous/internals/diagrams/tools-pmc.mmd create mode 100644 entity-framework/core/miscellaneous/internals/diagrams/tools-pmc.png create mode 100644 entity-framework/core/miscellaneous/internals/index.md create mode 100644 entity-framework/core/miscellaneous/internals/tools.md diff --git a/entity-framework/core/miscellaneous/internals/diagrams/generate.cmd b/entity-framework/core/miscellaneous/internals/diagrams/generate.cmd new file mode 100644 index 0000000000..dc7883555f --- /dev/null +++ b/entity-framework/core/miscellaneous/internals/diagrams/generate.cmd @@ -0,0 +1,2 @@ +:: npm install -g @mermaid-js/mermaid-cli +FOR %%f IN (*.mmd) DO mmdc -i %%f -o %%~nf.png diff --git a/entity-framework/core/miscellaneous/internals/diagrams/tools-cli.mmd b/entity-framework/core/miscellaneous/internals/diagrams/tools-cli.mmd new file mode 100644 index 0000000000..37dfe69c26 --- /dev/null +++ b/entity-framework/core/miscellaneous/internals/diagrams/tools-cli.mmd @@ -0,0 +1,3 @@ +flowchart + read[/Read project metadata/] --> build + build[Build startup project] --> ef.exe diff --git a/entity-framework/core/miscellaneous/internals/diagrams/tools-cli.png b/entity-framework/core/miscellaneous/internals/diagrams/tools-cli.png new file mode 100644 index 0000000000000000000000000000000000000000..7031eba45f15adaccedcb2de0694c01bd5aad963 GIT binary patch literal 5348 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 UFAVaC*Omb72ana^s`gL+1M*Q6wEzGB literal 0 HcmV?d00001 diff --git a/entity-framework/core/miscellaneous/internals/diagrams/tools-overview.mmd b/entity-framework/core/miscellaneous/internals/diagrams/tools-overview.mmd new file mode 100644 index 0000000000..f50499e834 --- /dev/null +++ b/entity-framework/core/miscellaneous/internals/diagrams/tools-overview.mmd @@ -0,0 +1,4 @@ +flowchart + dotnet-ef --> ef.exe + pmc[PMC Tools] --> ef.exe + ef.exe --> EFCore.Design.dll \ No newline at end of file diff --git a/entity-framework/core/miscellaneous/internals/diagrams/tools-overview.png b/entity-framework/core/miscellaneous/internals/diagrams/tools-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..176d321d539271ca51ec198707dccd3028ab6283 GIT binary patch literal 5885 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 literal 0 HcmV?d00001 diff --git a/entity-framework/core/miscellaneous/internals/diagrams/tools-pmc.mmd b/entity-framework/core/miscellaneous/internals/diagrams/tools-pmc.mmd new file mode 100644 index 0000000000..467a1ba07d --- /dev/null +++ b/entity-framework/core/miscellaneous/internals/diagrams/tools-pmc.mmd @@ -0,0 +1,4 @@ +flowchart + read[/Read project metadata/] --> build + build[Build startup project] --> ef.exe + ef.exe --> open[Open files] diff --git a/entity-framework/core/miscellaneous/internals/diagrams/tools-pmc.png b/entity-framework/core/miscellaneous/internals/diagrams/tools-pmc.png new file mode 100644 index 0000000000000000000000000000000000000000..52290f60dc69adb8166c3a51a7918af24e72577b GIT binary patch literal 6498 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 z rU52Tc+@K<$fwar}|88g`t5y8cOyFZ`=coQOq0zr*tW&1_==pyDbw;pD literal 0 HcmV?d00001 diff --git a/entity-framework/core/miscellaneous/internals/index.md b/entity-framework/core/miscellaneous/internals/index.md new file mode 100644 index 0000000000..9aa19a4eba --- /dev/null +++ b/entity-framework/core/miscellaneous/internals/index.md @@ -0,0 +1,30 @@ +--- +title: Architecture - EF Core +description: The internal architecture of Entity Framework Core +author: bricelam +ms.date: 11/27/2023 +uid: core/miscellaneous/internals/index +--- +# EF Core Architecture + +In 2010, Scott Hanselman associated Entity Framework with a magic unicorn. That's because there's a lot of magic going on behind the scenes that users generally doesn't have to think about. If you've ever wondered how some of that magic works, these docs are for you. They cover the architecture and implementation details of various parts of EF Core. + +## Articles + +Here are the articles we've written so far. Use issue [#1920](https://github.com/dotnet/EntityFramework.Docs/issues/1920) to let us know what else you'd like to see! + +- [Design-time tools](xref:core/miscellaneous/internals/tools) + +## Community Standup + +The EF team produces community standup videos, where we discuss various aspects of .NET and data access. Some of these have explored EF internals, and can be a good way to understand the general architecture of EF. + +- [How to Add a Feature to EF Core](https://www.youtube.com/watch?v=9OMxy1wal1s&list=PLdo4fOcmZ0oX0ObHwBrJ0vJpZ7PiYMqeA) +- [Internal Dependency Injection](https://www.youtube.com/watch?v=pYhe-Mt0HzI&list=PLdo4fOcmZ0oX0ObHwBrJ0vJpZ7PiYMqeA) +- [DbContext Configuration and Lifetime](https://www.youtube.com/watch?v=NPgFlqXPbK8&list=PLdo4fOcmZ0oX0ObHwBrJ0vJpZ7PiYMqeA) +- [IQueryable, LINQ and the EF Core query pipeline](https://www.youtube.com/watch?v=1Ld3dtnTrMw&list=PLdo4fOcmZ0oX0ObHwBrJ0vJpZ7PiYMqeA) +- [Model Building](https://www.youtube.com/watch?v=FYz0rAxQkC8&list=PLdo4fOcmZ0oX0ObHwBrJ0vJpZ7PiYMqeA) + +## See also + +- [ASP.NET Core Architecture Series](https://www.youtube.com/playlist?list=PLdo4fOcmZ0oUDW57sHWGT9Cfp9lAEx3lU) diff --git a/entity-framework/core/miscellaneous/internals/tools.md b/entity-framework/core/miscellaneous/internals/tools.md new file mode 100644 index 0000000000..30c6f993bf --- /dev/null +++ b/entity-framework/core/miscellaneous/internals/tools.md @@ -0,0 +1,132 @@ +--- +title: Design-time Tools Architecture - EF Core +description: The architecture of design-time tools in Entity Framework Core +author: bricelam +ms.date: 11/27/2023 +uid: core/miscellaneous/internals/tools +--- +# Design-time Tools Architecture + +The design-time tools are the part of EF that bootstrap design-time operations such as scaffolding a model or managing migrations. They are responsible for instantiating DbContext objects for use at design time. + +![Mermaid diagram of the high-level tools flow.](diagrams/tools-overview.png) + +There are two primary entry points: dotnet-ef and the NuGet Package Manager Console (PMC) EF Core tools. Both of these are responsible for gathering information about the user's projects, compiling them, then calling ef.exe which eventually calls the design-time entry points inside EFCore.Design.dll. + +## dotnet-ef + +dotnet-ef is a [.NET Tool](/dotnet/core/tools/global-tools-how-to-create). The dotnet- prefix allows it to be invoked as part of the main dotnet command: `dotnet ef`. + +There are two primary inputs to this command: the startup project and the target project. dotnet-ef is responsible for reading information about these projects then compiling them. + +![Mermaid diagram of dotnet-ef flow.](diagrams/tools-cli.png) + +It reads information about the projects by injecting an MSBuild .targets file and calling the custom MSBuild target. The .targets file is compiled into dotnet-ef as an emended resource. The source is located at [src/dotnet-ef/Resources/EntityFrameworkCore.targets](https://github.com/dotnet/efcore/blob/main/src/dotnet-ef/Resources/EntityFrameworkCore.targets). + +It has a bit of logic at the beginning to handle multi-targeting projects. Essentially, it just picks the first target framework and re-invokes itself. After a single target framework has been determined, it writes several MSBuild properties like AssemblyName, OutputPath, RootNamespace, etc. to a temporary file that dotnet-ef then reads. + +> [!TIP] +> .NET 8 adds a new, streamlined way to read MSBuild properties that will enable us to remove this .targets file. See issue [#32113](https://github.com/dotnet/efcore/issues/32113). + +We need to inject this target into both the startup and target project. We do that by leveraging an MSBuild hook created for NuGet and other package managers. That hook automatically loads any file under `$(MSBuildProjectExtensionsPath)` with a name matching the pattern `$(MSBuildProjectName).*.targets`. Unfortunately, we don't know the actual value of the MSBuildProjectExtensionsPath property, and we need it before we can read any MSBuild properties. So, we assume it's set to the default value of `$(MSBuildProjectDirectory)\obj`. If it's not, the user must specify it using the `--msbuildprojectextensionspath` option. + +After we've collected the project information, we compile the startup project. We assume that the target project will also be compiled transitively. + +Then dotnet-ef invokes ef.exe. + +## PMC Tools + +The PMC tools perform a similar function as dotnet-ef, but use Visual Studio APIs instead of MSBuild. They ship as the Microsoft.EntityFrameworkCore.Tools package. They are a special VS-aware [PowerShell module](/powershell/scripting/developer/module/writing-a-windows-powershell-module) that automatically gets loaded into the [NuGet Package Manager Console](/nuget/consume-packages/install-use-packages-powershell) via [init.ps1](https://github.com/dotnet/efcore/blob/main/src/EFCore.Tools/tools/init.ps1). Like dotnet-ef, each command take two primary inputs: the startup project and the target project. But the default values from these are taken from the IDE. The target project defaults to the project specified as the **Default project** inside the Package Manager Console. The startup project defaults to the one specified as the startup project (via **Set as Startup Project**) in Solution Explorer. + +![Mermaid diagram of PMC Tools flow.](diagrams/tools-pmc.png) + +The PMC tools gather information about the projects via the [EnvDTE](/dotnet/api/envdte.dte) APIs whenever possible. Occasionally, it needs to drop down to the [Common Project System](https://github.com/microsoft/VSProjectSystem) (CPS) or MSBuild APIs. The modern C# project system implementation source is available under the [dotnet/project-system](https://github.com/dotnet/project-system) project on GitHub. + +After collecting the information, it builds the entire solution. + +> [!TIP] +> Issue [#9716](https://github.com/dotnet/efcore/issues/9716) is about updating it to only build the startup project. + +Then, like dotnet-ef, it invokes ef.exe. The PMC Tools have a bit of extra logic after invoking ef.exe to open any files created by a command to provide a more integrated experience. + +## ef.exe + +Sometimes referred to as the inside man, ef.exe (for lack of a better name) ships as part of both dotnet-ef and the PMC Tools as a set of binaries. There are various binaries for different target frameworks and platforms. + +* tools/ + * net461/ + * any/ + * **ef.exe** + * win-x86/ + * **ef.exe** + * win-arm64/ + * **ef.exe** + * netcoreapp2.0/ + * any/ + * **ef.dll** + +The .NET Framework assemblies are only invoked for EF Core 3.1 projects and earlier targeting .NET Framework. By design, you can use the latest version of the tools on projects that use older versions of EF. There is no x64 because the assembly under the any directory targets the AnyCPU platform which runs as x64 on both x64 and arm64 versions of Windows. + +The .NET Core 2.0 assembly is used for projects targeting .NET Core or .NET 5 and newer. + +The primary responsibility of ef.exe is to load the startup project's output assembly and invoke the design-time entry points inside EFCore.Design.dll. + +On .NET Framework, we use a separate AppDomain to load the project assembly passing the project's App/Web.config file to honor and binding redirects added by NuGet or the user. + +On .NET Core/5+, we invoke ef.dll using the project's .deps.json and .runtimeconfig.json files to emulate the project's actual runtime and assembly loading behavior. + +```dotnetcli +dotnet exec ef.dll --depsfile startupProject.deps.json --runtimeconfig startupProject.runtimeconfig.json +``` + +> [!TIP] +> Issue [#18840](https://github.com/dotnet/efcore/issues/18840) is primarily about using [AssemblyLoadContext](/dotnet/core/dependency-loading/understanding-assemblyloadcontext) instead of `dotnet exec` to load the user's assembly. This should enable the tools to work with more project types including those targeting Android and iOS. + +After everything is set up to be loaded, ef.exe calls into EFCore.Design.dll via reflection and Activator.CreateInstance (or AppDomain.CreateInstance on .NET Framework). + +## EFCore.Design.dll + +EFCore.Design.dll, or more accurately, Microsoft.EntityFrameworkCore.Design.dll contains all the design-time logic for EF Core. All the entry points are inside the [OperationExecutor](https://github.com/dotnet/efcore/blob/main/src/EFCore.Design/Design/OperationExecutor.cs) class. A lost of the strangeness in the design of this class (MarshallByRefObject, nested types, etc.) stems from needing to invoke it across AppDomains on .NET Framework. A lot could be simplified if this requirement was removed. All of the signatures are weakly typed to enable both forward and backwards compatibility with the tools. Remember that different versions of the tools can be used to invoke projects using different versions of EF. + +In addition to the executor, [DbContextActivator](https://github.com/dotnet/efcore/blob/main/src/EFCore.Design/Design/DbContextActivator.cs) is another important type in this assembly. It's used by some of the ASP.NET Web Tools components to instantiate a user's DbContext at design time. + +### Creating a DbContext + +Before any specific design-time logic runs, a DbContext instance is typically required. The user can specify a simple or fully-qualified, case-insensitive type name for the DbContext, or they can not specify one if there is only a single DbContext type. Either way, we need to discover all the DbContext types before we narrow it down to a single one. The logic for discovering DbContext types live in the FindContextTypes method of [DbContextOperations](https://github.com/dotnet/efcore/blob/main/src/EFCore.Design/Design/Internal/DbContextOperations.cs). + +We look for DbContext types using various sources. + +* Referenced by IDesignTimeDbContextFactory\ implementations in the startup assembly. +* DbContexts added to the application service provider. To get a list of all context types, we get everything registered as `DbContextOptions` and look at the ContextType property. (See below for how we get the application service provider.) +* Types derived from DbContext in both the startup and target assemblies + +We also use various ways of instantiating the type. Here they are in order of precedence. + +1. Using an IDesignTimeDbContextFactory\ implementation +2. Using an IDbContextFactory\ from the application service provider +3. Using ActivatorUtilities.CreateInstance + +### Finding application services + +For the hightest fidelity to runtime behavior, we try to get the DbContext instance directly from the application service provider. We share this logic with the ASP.NET Core tooling. It's maintained as part of [dotnet/runtime](https://github.com/dotnet/runtime) project on GitHub under the [Microsoft.Extensions.HostFactoryResolver](https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.HostFactoryResolver) directory. + +In a nutshell, here are some of the strategies it uses. + +* Look for a method named BuildWebHost, CreateWebHostBuilder, or CreateHostBuilder next to the assembly entry point + * Build the host and get the services from the Services property +* Call the assembly entry point + * Intercept the services while building the host and terminate before actually starting the host + +### Design-time services + +In addition to the application services and the internal DbContext services, there is a third set of [design-time services](xref:core/cli/services). These aren't added to internal service provider since they're never needed at runtime. The design-time services are built by [DesignTimeServicesBuilder](https://github.com/dotnet/efcore/blob/main/src/EFCore.Design/Design/Internal/DesignTimeServicesBuilder.cs). There are two main path--one with a context instance and one without. The one without is primarily used when scaffolding a new DbContext. There are several extensibility points here to allow the user, providers, and extensions to override and customize the services. + +The user can customize services by adding an implementation of `IDesignTimeServices` to the startup assembly. + +Providers can customize services by adding the `DesignTimeProviderServices` attribute to their assembly. This points to an implementation of IDesignTimeServices. + +Extensions can customize services by adding `DesignTimeServicesReference` attributes to the target or startup assembly. If the attribute specifies a provider, it will only be added when that provider is in use. + +### Logging and exceptions + +After instantiating the DbContext, we wire up its logging to the tool's output. This enables output to be generated from the runtime. Any unhandled exceptions will also be written to the output. There is a special exception type `OperationException` that can be thrown to gracefully terminate the tools and show a simple error message without a stack trace. diff --git a/entity-framework/toc.yml b/entity-framework/toc.yml index 91b17d1715..8249ec758c 100644 --- a/entity-framework/toc.yml +++ b/entity-framework/toc.yml @@ -368,6 +368,13 @@ href: core/miscellaneous/multitenancy.md - name: Plug-in APIs href: core/miscellaneous/plugins.md + - name: EF Core Architecture + displayName: Internals + items: + - name: Overview + href: core/miscellaneous/internals/index.md + - name: Design-time tools + href: core/miscellaneous/internals/tools.md - name: Database providers items: