一. 反向工程
反向工程是基于数据库架构,生成的实体类和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 中的参数和—schema
CLI 中的选项可用于包含在架构中的每个表。
-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.4 Fluent API 或数据注释
默认情况下,使用Fluent API配置实体类型。在PMC中指定
-DataAnnotations
或在CLI中指定 --data-annotations
的情况下使用数据注释。下面二个代码块, 一个是使用Fluent API配置的,一个是使用数据注释,二者实现功能上一样。
//Fluent API配置
entity.Property(e => e.Title)
.IsRequired()
.HasMaxLength(); //数据注释
[Required]
[StringLength()]
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 类添加其他构造函数,方法,属性等。即使您打算再次对模型进行逆向工程,这种方法仍然有效。
参考文献