65.9K
CodeProject 正在变化。 阅读更多。
Home

Entity Framework 7 – Database First – 使用 EFCorePowerTools

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2023 年 5 月 26 日

CPOL

7分钟阅读

viewsIcon

12262

downloadIcon

142

关于使用 GUI 工具 EFCorePowerTools 的 EF7 – Database First 方法的教程

1. 引言

Entity Framework Core 倾向于“代码优先”方法,而有点忽视“数据库优先”方法,这导致(除其他外)Visual Studio 中“数据库优先”的 GUI 界面没有官方实现(截至 2023 年 5 月)。官方建议用户使用命令行 (CLI) 将数据库架构“逆向工程”为 C# 实体类。与 GUI 使用相比,命令行命令的使用总是难以记住且不直观。

然而,开源 Visual Studio 扩展 EFCorePowerTools 可用,它提供了一个官方未提供的 GUI 工具。它非常实用,甚至似乎比“官方”命令行“CLI EF Core 工具”功能更多。

本文旨在概述“逆向工程”数据库并创建 EF7 实体类以用于严肃应用程序的实际步骤。

1.1. “数据库优先”方法的重要性

许多信息系统,特别是银行系统,都是“以数据为中心”的,其中数据库扮演着核心角色。应用程序围绕数据库组织,数据库是此类组织宇宙的中心。数据库的更改通常由独立的数据库分析师或业务分析师完成,应用程序需要应对数据库模式的更改并使其数据访问层 (DAL) 适应由其他参与者对数据库进行的更改。通常,有多个应用程序在使用,其中一些是遗留应用程序,使用 ADO.NET 技术或类似技术。在这种情况下谈论“代码优先”方法是不现实的。对于使用 EF/.NET 的应用程序,唯一可能的方法是“数据库优先”,并且围绕数据库的其他应用程序也需要应用它们自己的类似“数据库优先”步骤,例如为 ADO.NET 重新创建模型等。因此,Microsoft Entity Framework 团队如此粗鲁地忽视 EF7 Core 中的“数据库优先”方法并将其推到命令行 (CLI) 是一个巨大的失望。然而,非官方的 GUI EFCorePowerTools 工具是可用的。

1.2. EFCorePowerTools

在本文中,我们将研究 EFCorePowerTools [3],它是一个用于实现 EF7 Core“数据库优先”方法的 GUI 工具。这不是“官方”的 Microsoft 工具,而是“社区开源”工具。在我看来,它是一个高度实用的工具,甚至支持存储过程,而本文撰写时(2023 年 5 月),“官方”命令行“CLI EF Core 工具”不支持存储过程。

1.3. CLI EF Core 工具

Microsoft 为“数据库优先”方法提供了“官方”命令行“CLI EF Core 工具”。它们不是本文的主题。您可以在我的文章 [6] 中找到它们的描述。

2. 示例项目

2.1. 示例控制台 .NET7 应用程序

我们创建了一个示例控制台 .NET7 应用程序,我们将使用它。请使用 NuGet 包管理器向应用程序添加以下包(依赖项),如屏幕截图所示。

  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.SqlServer

2.2. 示例 SqlServer 数据库

我们将使用一个示例 SqlServer 数据库 Northwind。由于有许多数据库对象,我们将只关注一个

  1. 表“Customers”,
  2. 视图“Invoices”,
  3. 存储过程“CustOrdersOrders

它们在屏幕截图中进行了概述。我们只需检查这些对象的“逆向工程”情况。

3. 安装 EFCorePowerTools

EFCorePowerTools 可作为免费的 Visual Studio 扩展使用。

4. 逆向工程实体(Scaffolding)

4.1. 数据库优先 – 创建模型

现在是时候做实际工作了。下面是显示如何创建 EF 模型的屏幕截图。我喜欢我的实体名称尽可能与表名称相似,这就是使用某些标志的原因。此外,我不想将数据库连接字符串嵌入到代码中,我希望使用配置文件并从那里加载它。另外,我希望我的模型位于一个名为 NorthwindDB 的单独文件夹中。

这是我们应用程序中生成的模型

请注意,已为 1) 表“Customers”,2) 视图“Invoices” (绿色)创建了实体。
为了支持 3) 存储过程“CustOrdersOrders”,已生成了几个类(橙色)。
此外,数据库上下文文件 NorthwindContext 已生成(黄色)。

4.2. 支持存储过程

EFCorePowerTools 提供了对存储过程的支持,而本文撰写时(2023 年 5 月),“官方”命令行“CLI EF Core 工具”中缺少此功能。一些论坛上的文章声称,有些人看到 EFCorePowerTools 在某些情况下支持存储过程的能力存在一些限制,例如当一个存储过程调用另一个存储过程时。这就是为什么“数据库优先”方法没有得到 Microsoft 官方全面支持令人遗憾的原因。它们在 EF6 设计 GUI 工具中得到了全面支持(来自 .NET 4.8 框架)。

如果迁移到 EF7 Core,却发现只有可用的“社区开源”工具偶尔会出现 bug,那会有点问题。

例如,在我的 SqlServer 生产系统中,我有大约 300 个存储过程,其他团队的人有时会更改一些存储过程,如果工具无法帮助我应对这些更改,我需要手动检测它们,或者等待报告 bug 才能收到更改通知。

4.3 创建模型的替代命令——偏爱属性

这是逆向工程 (Scaffolding) 实体的替代命令,如果您希望使用属性(而不是默认的流畅 API)来配置实体类,请使用此命令。

5. 读取配置文件

为了使应用程序更专业,我们将数据库连接字符串放入配置文件 appsettings.json 中,并创建工厂方法来创建 DbContext。我们不想对 NorthwindContext 类进行更改,因为如果重新生成 EF 模型,更改将丢失。

{
  "ConnectionStrings": {
    "NorthwindConnection": "Data Source=.;User Id=sa;
     Password=dbadmin1!;Initial Catalog=Northwind;Encrypt=False",
  }
}

您需要从 NuGet 包管理器安装更多包

internal class NorthwindContextFactory : IDesignTimeDbContextFactory<NorthwindContext>
    {
        static NorthwindContextFactory()
        {
            IConfiguration config = new ConfigurationBuilder()
               .SetBasePath(Directory.GetCurrentDirectory())
               .AddJsonFile("appsettings.json", true, true)
               .Build();

            connectionString = config["ConnectionStrings:NorthwindConnection"];
            Console.WriteLine("ConnectionString:"+connectionString);
        }

        static string? connectionString = null;
        
        public NorthwindContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<NorthwindContext>();

            optionsBuilder.UseSqlServer(connectionString);

            return new NorthwindContext(optionsBuilder.Options);
        }
    }

这是应用程序现在的样子

6. 测试应用程序

我们将创建一些代码来测试我们通过 EF 生成的模型。这是测试代码

using Example2.NorthwindDB;
using Example2;

Console.WriteLine("Hello from Example2");

using NorthwindContext ctx = 
      new NorthwindContextFactory().CreateDbContext(new string[0]);

Console.WriteLine("Table Customers ==================================");
var tableCustomers = ctx.Customers.Where(p => p.Country == "Germany");
foreach (var customer in tableCustomers)
{
    Console.WriteLine("Customer Name: " + customer.ContactName);
}

Console.WriteLine("View Invoices ==================================");
var viewInvoices = ctx.Invoices.Where(p => p.ShipCity == "Graz");
foreach (var invoice in viewInvoices)
{
    Console.WriteLine("ShipName: " + invoice.ShipName);
}

Console.WriteLine
   ("Stored Procedure CustOrdersOrders ==================================");
List<CustOrdersOrdersResult>? custOrders = 
               await ctx.GetProcedures().CustOrdersOrdersAsync("ALFKI");
foreach (var custOrder in custOrders)
{
    Console.WriteLine("OrderID: " + custOrder.OrderID);
}

这是执行结果

7. 数据库更改

那么,如果您更改了数据库模式怎么办?您需要重新生成 EF 模型,上述过程将覆盖现有类。这就是为什么您不能将任何代码放入生成的类中,因为新的 EF 模型生成将擦除您的更改。但是,您可以并且需要利用这些类是作为 partial 创建的事实,因此您可以用自定义的 partial 类扩展生成的类。

8. 结论

我们展示了如何使用 GUI 工具 EFCorePowerTools 生成“数据库优先”EF7 模型类。

看起来“社区开源” EFCorePowerTools 比“官方 Microsoft”命令行工具“CLI EF Core 工具”功能更强大,不仅因为 GUI 界面,还因为它们支持存储过程,而命令行工具在本文撰写时(2023 年 5 月)没有此功能。

有趣的是,在 [5] 中阅读了 Microsoft .NET 数据和 Entity Framework 的工程经理 Arthur Vickers 的评论,他表示

  • “诸如模型浏览器之类的可视化工具——这是我们不打算实现的。”
  • “……可视化工具(尤其是在 Visual Studio 中的那些)构建和维护成本都非常高……不确定 ROI 是否值得……”

因此,微软无意实现 GUI“数据库优先”EF7 Core 工具,并对“开源社区”提供一个工具感到满意。可悲的是,“官方微软”命令行工具“CLI EF Core 工具”甚至不支持存储过程,因此我们需要依赖“社区开源”的 EFCorePowerTools 来获得这种支持。

我想到的是“万一”情景,也就是“万一” “社区开源” EFCorePowerTools 的作者厌倦了维护/开发这个工具,而微软将 EF Core 升级到版本 8、9 等。用户将发现自己没有合适的工具可供使用。这就是为什么我希望有“官方微软”维护的工具可用,包括所有选项,包括对存储过程的支持,无论是 GUI 还是命令行工具。

9. 参考文献

10. 历史

  • 2023 年 5 月 26 日:初始版本
© . All rights reserved.