一. 反向工程
反向工程是基于数据库架构, 生成的实体类和 DbContext 类代码的过程, 对于 Visual Studio 开发, 建议使用 PMC. 对于其他开发环境, 请选择. NET Core CLI 工具(跨平台).
(1) 在程序包管理器控制台 (PMC) 工具中使用命令 Scaffold-DbContext 来进行反向工程.
(2) 在. NET 命令行接口 (CLI) 工具中使用 dotnet ef dbcontext scaffold 命令来进行反向工程.
1.1 Scaffold-DbContext 介绍
使用 Scaffold-DbContext 命令生成实体类型时, 数据库表必须具有主键, 没有主键的表不会被反向工程. 下面是 PMC 下的参数表格介绍, 对于 CLI 的 scaffold 参数介绍参考官网
参数 | 描述 |
-Connection <String> | 数据库的连接字符串。该参数,是必需的。 |
-Provider <String> | 要使用的提供程序。通常,这是 NuGet 包的名称,例如:Microsoft.EntityFrameworkCore.SqlServer。该参数,是必需的。 |
-OutputDir <String> | 放入文件的目录。路径是相对于项目目录的。 |
-ContextDir <String> | 放置 DbContext 文件的目录。路径是相对于项目目录的。 |
-Context <String> | DbContext 要生成的类的名称。 |
-Schemas <String []> | 用于生成实体类型的表的架构。如果省略此参数,则包括所有架构。例如在 sqlserver 上默认 dbo 架构 |
-Tables <String []> | 用于生成实体类型的表。如果省略此参数,则包括所有表。 |
-DataAnnotations | 使用属性配置模型(如果可能)。如果省略此参数,则仅使用 fluent API。 |
-UseDatabaseNames | 使用与数据库中显示的完全相同的表和列名称。如果省略此参数,则更改数据库名称以更符合 C#名称样式约定。 |
-Force | 覆盖现有文件 |
二. 命令参数详解
2.1 必备参数
-Connection <String > 是第一个参数是数据库的连接字符串. 工具将使用此连接字符串来读取数据库架构.-Provider <String > 是提供程序名称.
- // PowerShell
- Scaffold-DbContext 'Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook' Microsoft.EntityFrameworkCore.SqlServer
- // dotnet
- dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer
2.2 指定表和架构
默认情况下, 数据库架构中的所有表都被反向工程到实体类型, 可以限制哪些表是反向工程, 处理通过指定架构和表.
-Schemas 在 PMC 中的参数和 - schemaCLI 中的选项可用于包含在架构中的每个表.
-Tables (PMC) 和 --table(CLI) 可用于包括特定的表.
若要在 PMC 中包含多个表, 使用一个数组. 若要在 CLI 中包含多个表, 请多次指定选项.
- // PowerShell
- Scaffold-DbContext ... -Tables Blog, Post
- // dotnet
- dotnet ef dbcontext scaffold ... --table Blog --table Post
2.3 保留名称
默认情况下, 数据库的表名称和列名称是固定的, 以便更好地匹配实体名称和属性名称的. NET 命名约定. 在 PMC 中指定 - UseDatabaseNames 或在 CLI 中指定 --use-database-names, 使数据模型中的实体名称和属性名称与数据库中显示的的表和列名称完全相同. 如果省略此参数, 则可能会更改名称以更符合 C#命名约定.
2.4Fluent API 或数据注释
默认情况下, 使用 Fluent API 配置实体类型. 在 PMC 中指定 - DataAnnotations 或在 CLI 中指定 --data-annotations 的情况下使用数据注释. 下面二个代码块, 一个是使用 Fluent API 配置的, 一个是使用数据注释, 二者实现功能上一样.
- //Fluent API 配置
- entity.Property(e => e.Title)
- .IsRequired()
- .HasMaxLength(160);
- // 数据注释
- [Required]
- [StringLength(160)]
- public string Title { get; set; }
2.5 DbContext 名称
默认情况下, DbContext 上下文名称是(数据库名 + Context 后缀). 若要自定义一个 DbContext 上下文名称, 在 PMC 中指定 - Context 或在 CLI 中指定 --context .
2.6 目录和命名空间
默认情况下, 实体类和 DbContext 类被搭建到项目的根目录中, 并使用项目的默认命名空间. 在 PMC 中指定 - OutputDir 或在 CLI 中指定 --output-dir 将指定目录. 命名空间将是根命名称 + 子目录的名称.
下面使用 - ContextDir(PMC) 和 --context-dir(CLI) 来创建到一个单独的目录(Models), 存放实体类和 DbContext 类.
- // PowerShell
- Scaffold-DbContext ... -ContextDir Data -OutputDir Models
- // dotnet
- dotnet ef dbcontext scaffold ... --context-dir Data --output-dir Models
2.7 更新模型
当更改数据库后, 可能需要更新 EF Core 模型以反映这些更改. 如果数据库更改很简单, 则最简单的方法是手动对 EF Core 模型进行更改. 例如, 重命名表或列, 删除列或更新列的类型是在代码中进行的微不足道的更改. 如果, 数据库更改动作大. 一个常见的工作流程是使用 - Force(PMC)或 --force(CLI)再次从数据库对模型进行反向工程, 以使用更新的模型覆盖现有模型.
三. 演示
3.1 初始化反向工程
下面来演示一下, 关于准备工作和反向工程注意事项这里不在说明, 请参考 "asp.net core 系列 21 EF 现有数据库进行反向工程".
本篇使用 Visual Studio 开发, 使用 Package Manager Console 工具来进行反向工程管理, 用 PowerShell 脚本, 并附带上跨平台管理 的 dotnet 命令, 基于 EFGetStarted.AspNetCore.NewDb 数据库, 包括: Blogs 和 Posts 表来演示反向工程. 如下图所示:
- PM> Scaffold-DbContext "Data Source ={ip};Initial Catalog = EFGetStarted.AspNetCore.NewDb; User ID = hsr;Password =js*2015;" Microsoft.EntityFrameworkCore.SqlServer
- -OutputDir Models -Tables Blogs -Context ReverseDbContext -DataAnnotations -UseDatabaseNames
上面的一串命令参数中, 除了数据库的连接字符串, 使用的提供程序, 放入文件的目录, 其它参数都是可选的. 命令执行成功后, 将把 DbContext 上下文和实体类 (Blogs) 存放到 Models 文件夹中. 使用了 -Context 自定义 DbContext 上下文,-DataAnnotations 数据注释代替 Fluent API 配置, -UseDatabaseNames 与数据库中显示的的表和列名称完全相同.
3.2 更新模型
下面将 Blogs 表的 Url 字段类型长度从 Max 改为 400, 新增了 Address 字段, 使用 - Force 来覆盖现有文件. 命令成功后, 查看 Blogs 实体.
- PM> Scaffold-DbContext "Data Source =172.168.16.75;Initial Catalog = EFGetStarted.AspNetCore.NewDb; User ID = hsr;Password =js*2015;" Microsoft.EntityFrameworkCore.SqlServer
- -OutputDir Models -Tables Blogs -Context ReverseDbContext -DataAnnotations -UseDatabaseNames -Force
四. 其它说明
4.1 反向工程工作原理
(1) 反向工程开始时读取数据库架构. 它将读取有关表, 列, 约束和索引的信息.
(2) 接下来, 它使用的架构信息创建 EF Core 模型. 使用表来创建实体类型; 使用列来创建属性; 和外键用于创建关系.
(3) 最后, 该模型用于生成代码. 相应的实体类型的类, Fluent API 和数据批注已搭建基架以重新创建相同的模型从您的应用程序中.
4.2 反向工程哪些不起作用
(1) 并非所有关于模型的内容都可以使用数据库架构来表示. 例如: 有关继承层次结构, 拥有类型, 表拆分等不存在于数据库架构中. 因此, 这些构造将永远不能反向工程处理.
此外, EF Core 提供程序可能不支持某些列类型. 这些列不会包含在模型中.
(2) EF Core 需要每个实体类型有一个主键. 表没有主键是会反向工程.
(3) 您可以定义并发标记 EF Core 模型以防止两个用户在同一时间更新同一实体中. 有些数据库可以代替这种并发冲突, 例如 SQL Server 中的行版本控制. 但是这也不能反向工程处理.
4.3 反向工程自定义模型
EF Core 生成的代码可随意改变它. 只有再次对同一模型进行反向工程时, 才会重新生成它. Scaffold 代码代表一个可用于访问数据库的模型, 但它肯定不是唯一可以使用的模型.
可以自定义实体类和 DbContext 类以满足您的需要. 例如, 可以选择重命名类型和属性, 引入继承层次结构或将表拆分为多个实体. 您还可以从模型中删除非唯一索引, 未使用的序列和导航属性, 可选标量属性和约束名称. 还可以在单独的文件中使用另一个 partial 类添加其他构造函数, 方法, 属性等. 即使您打算再次对模型进行逆向工程, 这种方法仍然有效.
参考文献
EF 反向工程
来源: https://www.cnblogs.com/MrHSR/p/10425437.html