软件
20.08.2024 13:34

与他人分享:

分享

使用实体框架进行对象关系映射

当今,万维网是最大的计算机网络互联网上最受欢迎的服务。每天都有超过10万个新网站加入,从具有最低限度交互支持的静态网站到需要大量最新数据来执行功能的动态网站。
这张照片很说明问题。 (照片:Pixabay)
这张照片很说明问题。 (照片:Pixabay)

作者:丹尼斯·巴兰特、埃内吉·胡多布雷兹尼克


尽管技术发展迅速,但是管理关系数据库的主要语言仍然是 SQL。一种结构化查询语言,其根源可追溯到 20 世纪 70 年代,有许多改编的衍生产品(PostgreSQL、MySQL 等)。

编写 SQL 查询通常是一项非常耗时的工作,尤其是在数据库结构更复杂的情况下。与面向对象编程语言的典型做法不同,无需手动编写查询和对象转换,而是将类从源代码映射到数据模式,而不是反过来,这样更加自然,而且通常更简单。这节省了开发时间并且使得识别实体之间的关系变得更加容易。这种方法称为对象关系映射(ORM)。

对于 .NET 环境,微软提供了开源的 Entity Framework Core(简称 EF Core),它支持数据驱动开发(所谓的 Code First 方法),其中互连的数据被简单地收集到代表表的类中,框架使用它们来解析关系并以自己的格式创建数据库模式。这种方法的最大优点是无需了解 SQL 就可以在所需的数据库上安装数据模式。

EF Core 通过称为数据库提供程序的插件库与数据库通信,因此迁移到另一个数据库很容易。用户可以通过包管理器(C# 的 NuGet)安装这些。官方库仅适用于 Microsoft 的 SQL Server 和 Azure Cosmos DB 解决方案以及 SQLite 项目,但由于强大的开源社区,该框架几乎支持所有主要关系数据库(MySQL、PostgreSQL 等)。

作为数据建模的一个示例,让我们看一下表“学生”,该表具有属性名字(最多 20 个字符的字符串)、姓氏(最多 20 个字符的字符串)和唯一标识符(整数)。

学生表(自有来源)

在PostgreSQL中,我们对该表的定义如下:

PostgreSQL 中 Student 表的定义(自有来源)

除了定义名字和姓氏的基本类型之外,我们还要求它们永远不为空(NOT NULL)。 SERIAL 类型代表一个唯一的整数,在我们的例子中,它充当主键 Id。对于每个添加的实体,都会根据先前添加的身份的ID自动确定,该ID只是简单地递增。

使用 ORM 在应用程序逻辑的源代码中将表定义为类要容易得多,它会自动创建对象和相应的数据库要求。类属性上方的Key标签表示主键,Required表示该属性不能为空。

开发完成后,EF Core 允许我们自动从代码生成数据模式,并通过框架中包含的命令行工具将其部署到选定的数据库。数据库模式的逐步变化是通过所谓的迁移来管理的,这确保数据库与应用程序数据模型保持同步。新的迁移以特殊类的形式存储在 EF Core 中,是通过将当前数据模型与当前数据库模式(上次迁移的状态)进行比较创建的。

在 .NET 环境中使用 EF Core 定义 Student 表(自有源代码)

数据库连接由继承DbContext类的类抽象。其属性是映射到表的 DbSet 类型的实体的集合。

数据库连接类及定义学生表(自带源码)

上述查询编写框架使用 LINQ 语法,它代表了从各种来源检索和处理数据的统一方法。然后将查询转换为 SQL,并将结果本身转换回对象、其属性或对象表。

下面的示例显示了对已知入学编号的学生的查询。只需使用主键值(ID)调用一次 Find 方法就足够了。

使用 EF Core 进行学生查询的示例(自有来源)

如果我们想在不使用 ORM 工具的情况下实现相同的结果,则需要更多的代码。显示了使用 NpgSql 库的示例。首先,我们需要创建代表 SQL 查询和数据库读取的对象,但我们需要小心正确地包含参数以避免潜在的漏洞,例如SQL 注入。这次我们必须自己创建学生对象,但是我们必须小心查询中属性的顺序以及查询中出现错误的可能性。

使用 NpgSql 库(自己的源代码)查询学生的示例
上述问题的答案(来源自网络)

因此,对象关系映射为我们提供了一个抽象层,由于它映射自面向对象的开发计划,因此可以显著加快软件开发速度,因为 SQL 代码不必与源(通常是面向对象的)代码分开编写。编写良好的 ORM 支持应用程序设计的良好开发模式和实践,同时也允许不熟悉 SQL 的开发人员更轻松地将关系数据库集成到他们的应用程序中。

然而,必须强调的是,ORM 并不是一个完美的解决方案。其弱点恰恰在于它给我们提供的抽象概念。它生成的 SQL 代码比开发人员编写的要多得多,这会严重影响应用程序速度、隐藏不良的数据库访问实践,并且还会造成向后兼容性问题。虽然生成的代码在大多数情况下是正确的,但仍然建议手动检查和测试它。

对象关系映射不是 .NET 环境原生的功能。大多数针对不同语言的框架和库都提供该功能。例如 Python 的 Django、Go 的 Gorm、Java 的 Spring、JavaScript(或 Node.js)的 Prisma……




其他人在读什么?