ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

EF Core 设计时工具深度解析:Microsoft.EntityFrameworkCore.Tools 的 11 个 PMC 命令与其底层 ef 可执行文件调用链

EF Core 设计时工具深度解析:Microsoft.EntityFrameworkCore.Tools 的 11 个 PMC 命令与其底层 ef 可执行文件调用链 EF Core 设计时工具深度解析Microsoft.EntityFrameworkCore.Tools 的 11 个 PMC 命令与其底层 ef 可执行文件调用链【免费下载链接】efcoreEF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.项目地址: https://gitcode.com/GitHub_Trending/ef/efcoreEntity Framework CoreEF Core的设计时工具用于完成迁移管理Migrations和数据库反向工程Scaffold-DbContext 生成DbContext与实体类型两类开发期任务。其中Microsoft.EntityFrameworkCore.Tools包是专为 Visual Studio 包管理器控制台Package Manager Console, PMC提供的 PowerShell 工具集。本文以该包在仓库中的文档src/EFCore.Tools/README.md为主体骨架结合 src/EFCore.Tools 下的 NuGet 工程定义、PowerShell 模块源码tools/EntityFrameworkCore.psm1以及其实际调用的 ef 设计时命令行工具完整梳理如何安装该包、11 个可用命令的完整参数与默认值、每条 PMC 命令到ef子命令的映射关系以及模块在构建、启动项目校验、进程调用与输出着色等环节的底层实现。一、定位与安装方式EF Core 工具的定位由官方文档明确界定主要用途是管理 Migrations和通过反向工程数据库模式来脚手架生成DbContext与实体类型本包Microsoft.EntityFrameworkCore.Tools是面向PowerShell 的工具集运行于 Visual Studio 包管理器控制台PMC。安装方式是在 Visual Studio PMC 中执行Install-Package Microsoft.EntityFrameworkCore.Tools从 NuGet 包的工程定义src/EFCore.Tools/EFCore.Tools.csproj可以看到该包的几个关键属性这解释了它为什么只出现在设计时、不会进入应用依赖PackageIdMicrosoft.EntityFrameworkCore.Tools/PackageId发布名称即 PMC 中安装的包名DevelopmentDependencytrue/DevelopmentDependency标记为纯开发依赖NuGet 不会把它作为传递依赖带入最终应用IncludeBuildOutputtrue/IncludeBuildOutput注释说明是为了包含 pdb 符号文件TargetsForTfmSpecificContentInPackage中注册的AddPackContent目标会把tools/**/*打包到 NuGet 包的tools/目录并把ef.dll、ef.runtimeconfig.json、ef.pdb放到包的tools/net目录TfmSpecificPackageFile。也就是说PMC 命令真正的执行体ef可执行文件net/ef.dll就随包一起分发工程引用 src/ef/ef.csprojReferenceOutputAssemblyfalseef工程是 PMC 模块与dotnet-ef工具共用的设计时命令行实现EFCore.Tools.csproj 只在打包阶段取其产物不产生程序集引用。此外EntityFrameworkCore.psd1.in 通过Microsoft.DotNet.Build.Tasks.Templating在构建时以VersionPrefix渲染出生成后的.psd1模块清单保证模块版本号与包版本一致。二、模块加载机制init.ps1 与版本兼容包安装后NuGet 会执行tools/init.ps1src/EFCore.Tools/tools/init.ps1其逻辑是若 PowerShell 版本低于 3.0改为导入哑模块 EntityFrameworkCore.PS2.psm1——该文件定义了与正式命令同名同签名的函数但调用时抛出需要 Windows PowerShell 3.0 或更高版本的错误同时保留WarnIfEF6警告逻辑使得在过旧环境上用户仍能看到参数提示与版本升级指引若已加载EntityFrameworkCore模块则比较版本已加载版本不大于新模块版本时Remove-Module后重新导入否则跳过——避免 PMC 中重复安装导致新旧模块并存正常路径执行Import-Module ... -DisableNameChecking加载 tools/EntityFrameworkCore.psm1。模块清单EntityFrameworkCore.psd1.in声明了运行前提PowerShellVersion 3.0、PowerShellHostName Package Manager Host、PowerShellHostVersion 1.2。其FunctionsToExport完整列出了导出的 12 个函数11 个文档命令 已废弃的Enable-Migrations与about_EntityFrameworkCore帮助主题tools/about_EntityFrameworkCore.help.txt中的命令清单一致。三、完整命令参考继承自官方文档的命令表官方文档给出的 PMC 命令总表如下描述沿用原文档实现依据见 tools/EntityFrameworkCore.psm1PMC 命令用途Add-Migration添加一个新迁移Bundle-Migration创建一个用于更新数据库的可执行文件Drop-Database删除数据库Get-DbContext获取DbContext类型信息Get-Help EntityFramework显示 Entity Framework 命令的帮助信息Get-Migration列出可用迁移Optimize-DbContext生成DbContext所用模型的编译版本Remove-Migration删除最后一个迁移Scaffold-DbContext为指定数据库生成DbContext与实体类型类Script-DbContext从DbContext生成 SQL 脚本绕过迁移Script-Migration从迁移生成 SQL 脚本Update-Database将数据库更新到最后一个或指定迁移其中Get-Help EntityFramework对应 PowerShell 的about_EntityFrameworkCore帮助主题另外模块还保留了一个已废弃的Enable-Migrations函数调用时只提示Enable-Migrations is obsolete. Use Add-Migration to start using Migrations用于区分 EF6 的遗留命令。下面按源码逐命令给出参数语义、默认值与实现要点。3.1 Add-Migration —— 添加迁移参数来自 tools/EntityFrameworkCore.psm1 的函数签名与注释块参数说明-Name必填第 0 位迁移名称-OutputDir生成文件所在目录路径相对于项目目录默认Migrations-Context使用的DbContext-Project使用的项目-StartupProject启动项目默认为解决方案的启动项目-Namespace使用的命名空间默认与目录一致-NoBuild跳过构建适用于构建已是最新时-Args传递给应用程序的参数实现要点内部拼装参数数组migrations, add, $Name, --json说明 PMC 命令最终委托给ef的migrations add子命令并强制要求 JSON 输出--json结果被ConvertFrom-Json解析出migrationFile、metadataFile、snapshotFile三个文件路径若项目不是CPSConnected Projects System即现代 SDK 风格项目或显式关闭了EnableDefaultItems/EnableDefaultCompileItems传统 csproj 需要手工登记编译项模块会通过 DTE 的ProjectItems.AddFromFile把这三个文件登记进项目并OpenFile打开迁移文件、ShowConsole弹出输出窗口成功后打印To undo this action, use Remove-Migration.。对应的ef侧实现在 src/ef/Commands/MigrationsAddCommand.csExecute调用executor.AddMigration(name, outputDir, context, namespace)生成三个文件--json模式通过ReportJson输出migrationFile/metadataFile/snapshotFile——与 PMC 端解析的字段一一对应。3.2 Remove-Migration —— 删除最后一个迁移参数说明-Force若迁移已应用到数据库则回滚数据库-Offline不连接数据库仅删除迁移-Connection连接字符串默认为AddDbContext或OnConfiguring中指定者-Context/-Project/-StartupProject/-Args同上实现拼装migrations, remove, --json及--force/--offline/--connection对非 CPS 项目会解析 JSON 中的migrationFile/metadataFile/snapshotFile通过私有函数GetProjectItem在项目树中定位并Remove()保证删除文件的同时同步移除项目项。3.3 Update-Database —— 应用迁移参数说明-Migration目标迁移为0时回滚全部迁移默认为最后一个迁移与-Add联用时是新迁移的名称-Add以给定名称创建新迁移并立即应用-OutputDir生成文件目录相对项目目录必须与-Add联用-Namespace迁移使用的命名空间默认与目录一致必须与-Add联用-Connection连接字符串-NoBuild跳过构建-Context/-Project/-StartupProject/-Args同上源码中对参数有显式约束不带-Add却指定-OutputDir或-Namespace会直接抛异常The -OutputDir parameter requires the -Add parameter to be specified.。最终委托ef的database update子命令database, update附加--add/--output-dir/--namespace/--connection。3.4 Get-Migration / Get-DbContext —— 查询迁移与上下文Get-Migration参数-Connection、-NoConnect不连接数据库、-Context、-Project、-StartupProject、-Args委托ef的migrations list --json-NoConnect映射为--no-connect。Get-DbContext行为是双模的见 tools/EntityFrameworkCore.psm1 的Get-DbContext函数指定-Context时执行dbcontext info --json并返回反序列化后的单个对象未指定时执行dbcontext list --json把 JSON 数组拆开逐项输出并以Format-Table -Property safeName -HideTableHeaders呈现可用的DbContext类型名列表。3.5 Scaffold-DbContext —— 反向工程参数最多的命令完整签名参数说明-Connection必填第 0 位数据库连接字符串-Provider必填第 1 位提供程序如Microsoft.EntityFrameworkCore.SqlServer-OutputDir生成文件目录相对项目目录-ContextDirDbContext文件单独放置的目录相对项目目录-ContextDbContext名称默认为数据库名-Schemas要生成实体类型的模式集合指定后该模式下所有表和视图都会进模型-Tables要生成实体类型的表/视图可用schema.table/schema.view形式指定跨模式对象-DataAnnotations尽可能用特性配置模型省略时只用 Fluent API-UseDatabaseNames直接使用数据库中的表、视图、序列、列名-Force覆盖已存在文件-NoOnConfiguring不生成DbContext.OnConfiguring-Namespace/-ContextNamespace实体与DbContext类的命名空间默认与目录一致-NoPluralize不使用复数化器-Project/-StartupProject/-Args同上实现委托dbcontext scaffold子命令dbcontext, scaffold, $Connection, $Provider, --json-Schemas/-Tables逐个展开为多个--schema/--table参数完成后解析 JSON 的entityTypeFilescontextFile对非 CPS 项目逐一AddFromFile登记并自动打开生成的DbContext文件。3.6 Script-DbContext / Script-Migration —— 生成 SQL 脚本两者共用相同的输出处理逻辑指定-Output时作为目标文件相对路径会被解析为绝对路径未指定-Output时模块会把脚本写到项目的中间输出目录IntermediatePath下一个随机文件名的.sql文件[IO.Path]::GetRandomFileName()改扩展名并在生成后OpenFile打开该文件、弹出控制台窗口——这是 PMC 与dotnet-ef交互上的一个实用细节。差异参数Script-DbContext-Output、-Context、-Project、-StartupProject、-Args委托dbcontext script绕过迁移直接按模型生成脚本Script-Migration-From起始迁移默认0即初始库、-To目标迁移默认最后一个、-Idempotent生成可用于任意迁移状态的幂等脚本、-NoTransactions不生成事务语句、-Output委托migrations script。3.7 Bundle-Migration —— 打包可执行迁移工具参数说明-Output要创建的可执行文件路径-Force覆盖已存在文件-SelfContained连 .NET 运行时一起打包目标机器无需安装运行时-TargetRuntime目标运行时-Framework目标框架默认为项目中的第一个-Context/-Project/-StartupProject/-Args同上实现未指定-Framework时读取启动项目的FriendlyTargetFramework属性然后委托migrations bundle子命令。ef侧对应的生成器见 src/ef/Generators/BundleProjectGenerator.cs 与 src/ef/Generators/BundleProgramGenerator.cs。3.8 Drop-Database —— 删除数据库参数-Connection、-Context、-Project、-StartupProject、-Args。值得注意的实现细节Drop-Database使用了[CmdletBinding(SupportsShouldProcess $true, ConfirmImpact High)]执行前会先调用Get-DbContext拿到目标库的databaseName与dataSource然后以ShouldProcess触发 PowerShell 原生的-WhatIf/-Confirm高影响确认流程确认后才执行database drop --force。3.9 Optimize-DbContext —— 生成编译模型参数-OutputDir、-Namespace、-Context、-Project、-StartupProject、-Args委托dbcontext optimize子命令为DbContext所用的模型生成编译版本Compiled Model用于减少设计时/运行时的模型构建开销。四、参数与 Tab 补全Register-TabExpansion 的实现模块为每个命令注册了Register-TabExpansion补全规则这是 PMC 使用体验的核心来源以 tools/EntityFrameworkCore.psm1 为准-Context调用私有函数GetContextTypes其内部执行dbcontext list --json并跳过构建-skipBuild把每个上下文类型的safeName作为候选值——即输入-Context后按 Tab 会列出项目中所有DbContext类型-From/-ToScript-Migration与-MigrationUpdate-Database调用GetMigrations内部执行migrations list --no-connect --json列出迁移的safeName-Project/-StartupProject列出解决方案中的项目名Get-Project -All-ProviderScaffold-DbContext调用GetProviders列出项目已安装的 NuGet 包名-OutputDir等路径类参数被显式禁用了补全注释说明原因Otherwise, paths would be relative to the solution directory避免补全产生以解决方案目录为基准的相对路径歧义。五、底层调用链EF 函数如何运行 ef.dll所有 PMC 命令最终汇聚到私有函数EFtools/EntityFrameworkCore.psm1 中约 1245 行起它完成从 Visual Studio 环境到dotnet exec ef.dll ...进程的全部装配。调用链为PMC 函数 →EF私有函数 →dotnet exec tools/net/ef.dll 子命令 [选项]→ src/ef 中的具体*Command类 →Microsoft.EntityFrameworkCore.Design设计时服务。5.1 启动项目与框架校验EF函数按序执行以下校验与决策源码事实IsDocker按项目类型 GUID{E53339B2-1760-4266-BCC7-CA923CBCF16C}判断Docker 启动项目直接报错提示选择 ASP.NET Core Web Application 作为启动项目IsUWPUWP 项目不受支持报错并给出文档链接除非-skipBuild对应-NoBuild否则通过$DTE.Solution.SolutionBuild.Build($true)构建解决方案构建失败LastBuildInfo非零即抛Build failed.解析启动项目的TargetFrameworkMoniker得到框架标识.NETFramework报错PMC 工具不支持 .NET Framework 项目.NETStandard报错提示需要可执行的宿主项目因为无对应运行时.NETCoreApp允许但若是平台特定框架如TargetPlatformIdentifier非 Windows则报错若平台为 Windows 或仅含 RID 破折号后缀则给出建议实现IDesignTimeDbContextFactory的警告其他未知框架一律报错。5.2 dotnet exec 命令行装配对 .NET Core 启动项目EF函数拼装dotnet exec的参数--depsfile startupAssembly.deps.json复用启动项目的依赖清单从 CPS 属性ProjectAssetsFileproject.assets.json中解析packageFolders逐个转为--additionalprobingpath保证能定位 NuGet 包目录--runtimeconfig startupAssembly.runtimeconfig.json存在时否则回退到--fx-version RuntimeFrameworkVersion最后是模块目录下的net\ef.dll。随后追加一组设计时上下文参数这是ef能看到你的项目与模型的关键--verbose --no-color --prefix-output --assembly startup项目输出dll --project 项目全名 --startup-assembly startup目标文件 --startup-project startup项目全名 --project-dir 项目目录 --language C#|F#|... --configuration 活动配置名 --working-dir 当前目录条件性参数Web 项目追加--data-dir startupDir/App_Data存在RootNamespace时追加--root-namespaceNullable为enable/annotations时追加--nullable。此外还会通过dotnet build startupProject /t:ResolvePackageAssets /getItem:RuntimeCopyLocalItems拿到运行时引用列表若其中包含Microsoft.EntityFrameworkCore.Design.dll追加--design-assembly 路径即ef命令会加载该程序集来发现设计时服务与IDesignTimeDbContextFactory若包含Microsoft.CodeAnalysis.Workspaces.MSBuild且CopyLocaltrue还会把 NuGet 的contentFiles/any/any内容复制到输出目录。最后用ProcessStartInfoUseShellExecutefalse、CreateNoWindowtrue、UTF-8 标准输出、工作目录为启动项目目录启动进程。5.3 输出着色与错误上报ef进程以--prefix-output运行每行输出形如info: 消息/error: 消息/warn: 消息/data: 数据/verbose: 消息。EF函数按冒号拆分级别并做 8 字符对齐然后分派error→WriteErrorLine通过 VS 内部NuGetConsole.IPowerConsoleWindow的非公开ReportError走 NuGet 的错误呈现失败则回退为深红Write-Hostwarn→Write-Warninginfo→Write-Hostdata→Write-Output因此--json的结果会作为 PowerShell 管道对象返回供ConvertFrom-Json使用verbose→Write-Verbose。进程退出码非零时把标准错误逐行经WriteErrorLine输出后终止命令。5.4 项目与启动项目解析GetProject未指定-Project时用 PMC 的Get-Project当前项目GetStartupProject未指定-StartupProject时读取$DTE.Solution.SolutionBuild.StartupProjects若为单个路径会递归遍历解决方案项目GetSolutionProjects用栈做深度优先展开按FullName匹配出现未设置启动项目多个启动项目无法解析等情况时逐级Write-Warning并回退到所选项目。六、与 EF6 工具的冲突防护WarnIfEF6私有函数在Add-Migration、Update-DatabasePS2 模块中还有Enable-Migrations执行前检查是否同时加载了EntityFramework6或EntityFramework模块若是则警告Both Entity Framework Core and Entity Framework 6 are installed. The Entity Framework Core tools are running. Use EntityFramework6cmdlet for Entity Framework 6.——即提示用户 EF6 工具的同名命令需要带模块前缀调用避免混淆。七、适用前提与限制小结基于以上源码事实使用本工具时需满足的前提均可在 tools/EntityFrameworkCore.psm1 中找到对应判断环境Windows PowerShell 3.0、Package Manager Host 1.2模块清单声明低于 3.0 时命令可用但会提示升级项目启动项目必须是可执行的 .NET Core/.NET 项目.NET Framework、.NET Standard、Docker、UWP、非 Windows 平台特定框架项目会被拒绝或警告平台特定框架建议实现IDesignTimeDbContextFactory构建除-NoBuild场景外每次命令执行前会完整构建解决方案依赖启动项目的传递引用中需要包含Microsoft.EntityFrameworkCore.Design用于--design-assembly发现设计时能力。八、仓库内相关文件索引文件作用src/EFCore.Tools/README.md包文档定位、安装、命令总表src/EFCore.Tools/EFCore.Tools.csprojNuGet 包工程打包tools/与ef.dll到tools/netsrc/EFCore.Tools/EntityFrameworkCore.psd1.in模块清单模板版本渲染、运行前提、FunctionsToExportsrc/EFCore.Tools/tools/init.ps1安装脚本PS2 降级分支与模块版本管理src/EFCore.Tools/tools/EntityFrameworkCore.psm111 个 PMC 命令实现、Tab 补全、EF调用链src/EFCore.Tools/tools/EntityFrameworkCore.PS2.psm1PS2.0 兼容的哑模块src/EFCore.Tools/tools/about_EntityFrameworkCore.help.txtGet-Help EntityFramework帮助主题src/ef/Program.cs、src/ef/Commands/被调用的ef设计时 CLI 及其各子命令实现综合来看Microsoft.EntityFrameworkCore.Tools的设计是薄 PowerShell 封装 厚 CLI 内核PMC 命令只负责参数收集、项目/启动项目解析、JSON 结果消费文件登记、打开编辑器、弹出控制台而所有设计时逻辑都收敛在ef工程与Microsoft.EntityFrameworkCore.Design中——这也意味着在 PMC 之外使用dotnet-ef时二者共享同一套命令语义与选项只是参数形式从-PascalCase映射为kebab-case。【免费下载链接】efcoreEF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.项目地址: https://gitcode.com/GitHub_Trending/ef/efcore创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表