EF Core 8 Preview 4:原始集合和改进的 Contains

这篇具有很好参考价值的文章主要介绍了EF Core 8 Preview 4:原始集合和改进的 Contains。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:Shay Rojansky
翻译:Alan Wang
排版:Alan Wang

Entity Framework Core (EF Core) 8 预览版4今天在 NuGet 上发布!

基本信息

EF Core 8,或简称 EF8,是 EF Core 7 的后续,计划于2023年11月与 .NET 8 同时发布。

EF8 预览版本当前面向 .NET 6,因此可以与 .NET 6(LTS)或 .NET 7 一起使用。随着我们即将发布,这可能会更新到 .NET 8。

作为一个长期支持版本(LTS),EF8 将与 .NET 8 保持一致。详细信息请查看 .NET 支持策略。

EF8 Preview 4 的更新

EF Core 8.0 preview4 包含一些令人兴奋的查询转换新功能,以及一个重要的性能优化。让我们深入地看一看!

使用内联集合转换 LINQ Contains

在 EF 寻求将越来越多的 LINQ 查询转换为 SQL 的过程中,我们有时会遇到一些奇怪且有问题的情况。让我们来看看这样一个案例,它恰好也与一个投票率很高的 EF 性能问题有关。从简单的事情开始,假设你有一堆博客,并想查询出两个你知道名字的博客。您可以使用以下 LINQ 查询来执行此操作:

var blogs = await context.Blogs
    .Where(b => new[] { "Blog1", "Blog2" }.Contains(b.Name))
    .ToArrayAsync();

这将导致在 SQL Server 上生成以下 SQL 查询:

SELECT [b].[Id], [b].[Name]
FROM [Blogs] AS [b]
WHERE [b].[Name] IN (N'Blog1', N'Blog2')

看起来很棒!LINQ Contains 运算符有一个匹配的 SQL 构造——IN 表达式——它为我们提供了一个完美的转换。然而,这个查询中的名称作为常量嵌入到了 LINQ 查询中——因此也嵌入到了 SQL 查询中,通过我所说的内联集合(就是 new[] { ... } 部分):集合在查询本身中以行的形式指定。在许多情况下,我们无法做到这一点:博客名称有时只能作为变量使用,因为我们从其他来源读取它们,甚至可能从另一个 EF LINQ 查询中读取。

转换带有参数集合的 LINQ Contains

那么,当我们尝试做同样的事情,但在查询中嵌入一个变量而不是内联集合时,会发生什么呢?

var names = new[] { "Blog1", "Blog2" };

var blogs = await context.Blogs
    .Where(b => names.Contains(b.Name))
    .ToArrayAsync();

names 等变量嵌入到查询中时,EF 通常会通过数据库参数原样发送。这在大多数情况下都行得通,但对于这种特殊情况,数据库根本不支持将 IN 表达式与参数一起使用。换句话说,以下内容并不是有效的 SQL:

SELECT [b].[Id], [b].[Name]
FROM [Blogs] AS [b]
WHERE [b].[Name] IN @names

更广泛地说,关系数据库实际上并没有“列表”或“集合”的概念;它们通常处理逻辑上无序的、结构化的集合,例如表。SQL Server 确实允许发送表值参数,但这涉及到各种复杂情况,因此这并不是一个合适的解决方案(例如,在查询之前必须预先定义表类型及其特定结构)。

唯一的例外是 PostgreSQL,它完全支持数组的概念:你可以在表中有一个 int 数组列,查询它,并将数组作为参数发送,就像你可以使用任何其他数据库类型一样。这允许 EF PostgreSQL 提供程序执行以下转换:

Executed DbCommand (10ms) [Parameters=[@__names_0={ 'Blog1', 'Blog2' } (DbType = Object)], CommandType='Text', CommandTimeout='30']

SELECT b."Id", b."Name"
FROM "Blogs" AS b
WHERE b."Name" = ANY (@__names_0)

这与上面使用 IN 的内联集合转换非常相似,但使用了 PostgreSQL 特定的 ANY 构造,该构造可以接受数组类型。利用这一点,我们将博客名称数组作为 SQL 参数直接传递给 ANY—— @__names_0 ——并得到完美的转换。但是,我们能为其他数据库做些什么呢?在没有 PostgreSQL 的情况下?

目前为止,所有版本的 EF 都提供了以下转换

SELECT [b].[Id], [b].[Name]
FROM [Blogs] AS [b]
WHERE [b].[Name] IN (N'Blog1', N'Blog2')

但是等一下,这看起来很熟悉——这是我们上面看到的内联集合转换!事实上,由于我们无法参数化数组,我们只是将其值作为常量嵌入到 SQL 查询中。虽然 EF LINQ 查询中的 .NET 变量通常会成为 SQL 参数,但在这种特殊情况下,该变量已消失,其内容则被直接插入到了 SQL 中。

不幸的是,EF 生成的 SQL 因不同的数组内容而异——这是一种非常不正常的情况!通常,当您一次又一次地运行相同的 LINQ 查询(只更改参数值)时,EF 会向数据库发送完全相同的 SQL。这对于良好的性能至关重要:SQL Server 缓存 SQL,只在第一次看到特定的 SQL 时执行昂贵的查询计划(类似的 SQL 缓存在 PostgreSQL 的数据库驱动程序中实现)。此外,EF 本身有一个用于查询的内部 SQL 缓存,而这种 SQL 差异使缓存变得不可能,从而导致每个查询的 EF 消耗进一步增加。

但至关重要的是,不断变化的 SQL 对性能的负面影响超出了这个特定的查询。SQL Server(和 Npgsql)只能缓存一定数量的 SQL;在某些情况下,它们必须删除旧条目,以避免使用过多内存。如果您经常将 Contains 与变量数组一起使用,那么每个单独的调用都会导致在数据库中获取有价值的缓存条目,因为 SQL 很可能永远不会被使用(因为它们有特定的数组值)。这意味着您还将清除其他需要使用的重要 SQL 的缓存条目,并要求一次又一次地重新规划它们。

简而言之——不太好!事实上,这一性能问题是 EF Core repo 中投票率第二高的问题;与大多数性能问题一样,您的应用程序可能会在您不知情的情况下受到影响。当集合是一个参数时,我们显然需要一个更好的解决方案来转换 LINQ Contains 运算符。

使用 OpenJson 转换参数集合

让我们看看 SQL preview4 为这个 LINQ 查询生成了什么:

Executed DbCommand (49ms) [Parameters=[@__names_0='["Blog1","Blog2"]' (Size = 4000)], CommandType='Text', CommandTimeout='30']

SELECT [b].[Id], [b].[Name]
FROM [Blogs] AS [b]
WHERE EXISTS (
    SELECT 1
    FROM OpenJson(@__names_0) AS [n]
    WHERE [n].[value] = [b].[Name])

这个 SQL 确实是一个完全不同的东西;但是,即使不了解到底发生了什么,我们也可以看到博客名称是作为一个参数传递的,在 SQL 中通过 @__names_0 表示——类似于我们上面的 PostgreSQL 转换。那么这是怎么回事呢?

现代数据库内置了对 JSON 的支持;尽管具体情况因数据库而异,但所有数据库都支持在 SQL 中直接解析和查询 JSON 的一些基本形式。SQL Server 的 JSON 功能之一是 OpenJson 函数:这是一个“表值函数”,它接受 JSON 文档,并从其内容返回一个标准的关系行集。例如,以下 SQL 查询:

SELECT * FROM OpenJson('["one", "two", "three"]');

返回以下行集

[key] value type
0 one 1
1 two 1
2 three 2

输入的 JSON 数组已被有效地转换为关系型“表”,然后可以使用常用的 SQL 运算符对其进行查询。EF 利用这一点来解决“参数集合”问题:

  1. 我们将您的 .NET 数组变量转换为 JSON 数组…
  2. 我们将 JSON 数组作为一个简单的 SQL nvarchar 参数发送…
  3. 我们使用 OpenJson 函数来解压缩参数…
  4. 我们使用 EXISTS 子查询来检查是否有任何元素与博客的名称匹配。

这实现了我们的目标,即为 .NET 数组中的不同值提供一个单一的、不可变的SQL,并解决了 SQL 缓存问题。重要的是,在单独查看时,这个新转换实际上可能比以前的转换运行得慢一点——SQL Server 有时可以比新转换更有效地执行以前的 IN 转换;具体何时发生取决于数组中元素的数量。但关键的一点是,无论这个特定查询运行得多快,它都不会再导致其他查询从 SQL 缓存中被逐出,从而对整个应用程序产生负面影响。

我们正在研究对上述基于 OpenJson 的转换的进一步优化——preview4实现只是该功能的第一个版本。请继续关注此领域进一步的性能改进。

SQL Server 的旧版本

OpenJson 函数是在 SQLServer 2016(13.x)中引入的;虽然这是一个相当旧的版本,但它仍然受到支持,我们不想因为依赖它而破坏它的用户。因此,我们为您引入了一种通用的方法来告诉 EF 哪个 SQL Server 是目标 SQL Server,这将使我们能够利用较新的功能,同时为旧版本的用户保留向后的兼容性。要做到这一点,只需在配置上下文选项时调用新的 [UseCompatibilityLevel] 方法:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlServer(@"<CONNECTION STRING>", o => o.UseCompatibilityLevel(120));

120 参数是所需的 SQL Server 兼容性级别;120 对应 SQL Server 2014(12.x)。完成此操作后,EF 将生成先前的转换,将数组内容嵌入到 IN 表达式中。

可查询的原始集合列

我可以到此为止,我们已经有了一个很好的功能,解决了一个长期存在的性能问题。但让我们走得更远些!上述 Contains 的解决方案支持将原始集合表示为 JSON 数组,然后像查询中的任何其他表一样使用该集合。上面转换的 Contains 只是一个非常具体的例子,但我们可以做得更多。

假设每个博客也关联到一个标签集合。在经典的关系建模中,我们将其表示为 Blogs 表和 Tags 表之间的多对多关系,使用 BlogTags 联接表将两者链接在一起;EF Core 非常支持这种映射(参阅文档)。但是这种传统的建模可能有点重,需要两个额外的表和 JOIN,以及一个 .NET 类型来包装简单的字符串 Tag。让我们试着从不同的角度来看待这个问题。

由于 EF 现在支持原始集合,我们可以简单地在我们的博客类型中添加一个字符串数组属性:

public class Blog
{
    public int Id { get; set; }
    // ...
    public string[] Tags { get; set; }
}

这将导致 EF 生成以下表格:

CREATE TABLE [Blogs] (
    [Id] int NOT NULL IDENTITY,
    -- ...
    [Tags] nvarchar(max) NULL,
);

我们的新标签属性现在映射到了数据库中的单个 nvarchar(max) 属性。您现在可以添加带有一些标记的博客:

context.Blogs.Add(new Blog { Name = "Blog1", Tags = new[] { "Tag1", "Tag2" } });
await context.SaveChangesAsync();

…EF 将自动将您的 Tags.NET 数组编码为数据库中的 JSON 数组字符串:

Executed DbCommand (47ms) [Parameters=[@p0='foo' (Nullable = false) (Size = 4000), @p1='["Tag1","Tag2"]' (Size = 4000)], CommandType='Text', CommandTimeout='30']

INSERT INTO [Blogs] ([Name], [Tags])
OUTPUT INSERTED.[Id]
VALUES (@p0, @p1);

类似地,当从数据库中读取博客时,EF 将自动解码 JSON 数组并填充 .NET 数组属性。这一切都很美妙,但人们很长一段时间以来已经在通过在数组属性上定义值转换器来实现这一点了。事实上,我们的值转换器文档中有一个示例正好说明了这一点。那有什么大不了的?

正如我们使用 SQL EXISTS 子查询来转换 LINQ Contains 运算符一样,EF 现在允许您在此类原始集合列上使用任意 LINQ 运算符,就像它们是常规 DbSet 一样;换句话说,原始集合现在是完全可查询的。例如,要查找所有具有特定标记的博客,您现在可以使用以下 LINQ 查询:

var blogs = await context.Blogs
    .Where(b => b.Tags.Contains("Tag1"))
    .ToArrayAsync();

…EF 将转换为以下内容:

SELECT [b].[Id], [b].[Name], [b].[Tags]
FROM [Blogs] AS [b]
WHERE EXISTS (
    SELECT 1
    FROM OpenJson([b].[Tags]) AS [t]
    WHERE [t].[value] = N'Tag1')

这与我们在上面看到的参数的 SQL 完全相同,但应用于列!但让我们做一些更有趣的事情:如果我们不想查询所有有特定标签的博客,而是想查询有多个标签的博客呢?现在可以使用以下 LINQ 查询来完成此操作:

var tags = new[] { "Tag1", "Tag2" };

var blogs = await context.Blogs
    .Where(b => b.Tags.Intersect(tags).Count() >= 2)
    .ToArrayAsync();

这利用了更复杂的 LINQ 操作符:我们将每个博客的标签与一个参数集合相交,并查询出至少有两个匹配的博客。这将转化为以下内容:

Executed DbCommand (48ms) [Parameters=[@__tags_0='["Tag1","Tag2"]' (Size = 4000)], CommandType='Text', CommandTimeout='30']

SELECT [b].[Id], [b].[Name], [b].[Tags]
FROM [Blogs] AS [b]
WHERE (
    SELECT COUNT(*)
    FROM (
        SELECT [t].[value]
        FROM OpenJson([b].[Tags]) AS [t] -- column collection
        INTERSECT
        SELECT [t1].[value]
        FROM OpenJson(@__tags_0) AS [t1] -- parameter collection
    ) AS [t0]) >= 2

这很难理解,但我们使用了相同的基本机制:我们在列原始集合([b].[Tags])和参数原始集合(@__tags_0)之间执行交集,使用 OpenJson 将 JSON 数组字符串解包到行集中。

让我们来看最后一个例子。由于我们将原始集合编码为 JSON 数组,因此这些集合是自然有序的。在关系数据库中,这是一种非典型的情况——关系集在逻辑上总是无序的,必须使用 ORDER BY 子句才能获得任何确定性排序。

现在,标签列表通常是一个无序的袋子:我们不在乎哪个标签排在第一位。但是,为了这个例子,让我们假设您的博客的标签是有序的,更“重要”的标签排在第一位。在这种情况下,以某个值作为第一个标签查询所有博客可能是有意义的:

var blogs = await context.Blogs
    .Where(b => b.Tags[0] == "Tag1")
    .ToArrayAsync();

这将生成以下 SQL:

SELECT [b].[Id], [b].[Name], [b].[Tags]
FROM [Blogs] AS [b]
WHERE (
    SELECT [t].[value]
    FROM OpenJson([b].[Tags]) AS [t]
    ORDER BY CAST([t].[key] AS int)
    OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) = N'Tag1'

EF 生成一个 ORDER BY 子句,以确保 JSON 数组的自然顺序得到保留,然后使用限制来获取第一个元素。这种过于复杂的 SQL 已经得到了改进,之后的预览版将生成以下更严格的 SQL:

SELECT [b].[Id], [b].[Name], [b].[Tags]
FROM [Blogs] AS [b]
WHERE JSON_VALUE([b].[Tags], '$[0]') = N'Tag1'

总之,现在可以在原始集合上使用全套 LINQ 运算符,无论它们是列还是参数。这为以前从未转换过的查询打开了令人兴奋的转换可能性;我们期待看到您将使用的查询类型!

在使用基于 JSON 的原始集合之前,请仔细考虑索引和查询性能。大多数数据库允许将至少某些形式的查询索引到 JSON 文档中;但是任意的、复杂的查询(如上面的 intersect)可能无法使用索引。在某些情况下,传统的关系建模(例如多对多)可能更合适。
我们在上面提到,PostgreSQL 对数组有原生支持,所以在处理原始集合时不需要使用 JSON 数组编码。相反,原始数组集合(默认情况下)映射到数组,PostgreSQL unnest 函数用于将本机数组扩展到行集。

还有最后一件事:可查询的内联集合

我们讨论了包含原始集合的列和参数,但省略了最后一种类型——内联集合。您可能还记得,我们以以下 LINQ 查询开始了这篇文章:

var blogs = await context.Blogs
    .Where(b => new[] { "Blog1", "Blog2" }.Contains(b.Name))
    .ToArrayAsync();

查询中的 new[] { ... } 位表示内联集合。到目前为止,EF 仅在一些非常有限的场景中支持这些,例如 Contains 运算符。Preview 4现在提供了对可查询内联集合的完全支持,允许您在它们上使用全套 LINQ 运算符。

作为一个示例查询,让我们挑战自己,做一些更复杂的事情。以下查询为搜索至少有一个以ab开头标签的博客:

var blogs = await context.Blogs
    .Where(b => new[] { "a%", "b%" }
        .Any(pattern => b.Tags.Any(tag => EF.Functions.Like(tag, pattern))))
    .ToArrayAsync();

请注意,模式的内联集合——new[] { "a%", "b%" }—— 由 Any 运算符组成。现在这会转换为以下 SQL:

SELECT [b].[Id], [b].[Name], [b].[Tags]
FROM [Blogs] AS [b]
WHERE EXISTS (
    SELECT 1
    FROM (VALUES (CAST(N'a%' AS nvarchar(max))), (N'b%')) AS [v]([Value]) -- inline collection
    WHERE EXISTS (
        SELECT 1
        FROM OpenJson([b].[Tags]) AS [t] -- column collection
        WHERE [t].[value] LIKE [v].[Value]))

有趣的是“内联集合”行。与参数和列集合不同,我们不需要使用 JSON 数组和 OpenJson:SQL 已经有了通过VALUES 表达式指定内联表的通用机制。这就完成了这幅图——EF 现在支持查询任何类型的原始集合,无论是列、参数还是内联集合。

支持的和不支持的

Preview 4 带来了对 SQL Server 和 SQLite 的原始集合支持;PostgreSQL 提供程序也将更新以支持它们。然而,如上所述,这是关于原始集合的第一波工作——预计在未来的版本中会有进一步的改进。具体来说:

  • 还不支持自有的 JSON 实体中的原始集合
  • 某些提供程序尚不支持某些原始数据类型;例如,空间类型就是这样。
  • 我们可以围绕 OpenJSON 优化 SQL,以提高查询效率。

如何获取 EF8 Preview 4

EF 8 仅作为一组 NuGet 软件包分发。例如,要将 SQL Server 提供程序添加到项目中,可以使用 dotnet 工具执行以下命令:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 8.0.0-preview.4.23259.3

安装 EF8 命令行界面(CLI)

在执行 EF8 Core 迁移或脚手架命令之前,必须安装dotnet-ef 工具。

要全局安装该工具,请使用:

dotnet tool install --global dotnet-ef --version 8.0.0-preview.4.23259.3

如果您已经安装了该工具,则可以使用以下命令对其进行升级:

dotnet tool update --global dotnet-ef --version 8.0.0-preview.4.23259.3

The .NET Data Community Standup

.NET 数据访问团队现在每星期三太平洋时间上午10点、东部时间下午1点或 UTC 时间18:00进行直播。加入直播学习并询问有关 .NET 数据相关的问题。

  • 往期节目 YouTube 列表
  • 访问 .NET Community Standup 页面查看接下来的节目预告
  • 提交您对嘉宾、产品、演示或其他内容的想法

文档与反馈

所有 EF Core 文档:docs.microsoft.com/ef/。 请在 dotnet/efcore GitHub repo 上填写发现的问题或其他任何反馈。

帮助链接

可参考和访问以下链接:文章来源地址https://www.toymoban.com/news/detail-520175.html

  • EF Core Community Standup 播放列表:aka.ms/efstandups
  • 主要的文档:aka.ms/efdocs
  • What’s New in EF Core 8:aka.ms/ef8-new
  • What’s New in EF Core 7:aka.ms/ef7-new
  • EF Core 的 issue 和功能请求:github.com/dotnet/efcore/issues
  • Entity Framework 路线图:aka.ms/efroadmap
  • 每两周一次的更新:aka.ms/ef-news

到了这里,关于EF Core 8 Preview 4:原始集合和改进的 Contains的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ASP.NET Core Web API入门之三:使用EF Core

    一般来讲我们做项目都会用实体类跟数据库实体进行关系对应,这样的好处方便我们维护、增删改查,并且可以减少SQL的编写,从而统一风格,那么 Entity Framework Core 就是很不错的ORM框架。 1、跨数据库支持能力强大,只需修改配置就可以轻松实现数据库切换。 2、提升了开发效

    2024年02月10日
    浏览(55)
  • .NET使用一行命令轻松生成EF Core项目框架

    dotnet ef是Entity Framework Core(EF Core)的一个命令行工具,用于管理EF Core应用程序的数据库和代码。除了提供管理数据库的命令之外,dotnet ef还可以生成和管理实体和上下文代码。本文将介绍如何使用dotnet ef动态生成代码。 一、环境准备 1、项目准备 用vs2022新建一个.NET6的asp.

    2023年04月27日
    浏览(54)
  • NET8 ORM 使用AOT SqlSugar 和 EF Core

    .Net8的本地预编机器码NET AOT,它几乎进行了100%的自举。微软为了摆脱C++的钳制,做了很多努力。也就是代码几乎是用C#重写,包括了虚拟机,GC,内存模型等等。而需要C++做的,也就仅仅是引导程序,本篇通过代码来看下这段至关重要的引导程序的运作模式。      SqlSugar已经

    2024年02月05日
    浏览(54)
  • .NET6.0 EF Core 之 DB First生成实体类

    EF Core可以使用DB First模式生成实体类具体步骤如下: 因为.NET Core中默认不包含EF Core的工具和程序包,需要通过NuGet管理器安装对应的工具和程序包,这里使用SQL Server数据库。 Microsoft.EntityFrameworkCore.SqlServer:SQL Server数据库EF提供程序 Microsoft.EntityFrameworkCore.Design:设计时使用到

    2024年02月06日
    浏览(50)
  • .net 6 EF Core MySql数据库表生成实体类命令

    安装下面这几个包 Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Tools Microsoft.EntityFrameworkCore.Design Pomelo.EntityFrameworkCore.MySql Scaffold-DbContext “server=127.0.0.1;port=3306;database=DB;uid=root;pwd=pwdpwd;sslmode=none;” Pomelo.EntityFrameworkCore.MySql -OutputDir Models -Force -NoOnConfiguring -NoPluralize -Context “D

    2024年02月05日
    浏览(45)
  • .net core 创建WebAPI以及使用EF DBFirst框架使用方法与疑问解答(.net 6)

    EF语法包: 生成实体模型: 修改实体模型: 把生成的实体和上下文都输出到某个文件夹命令 增加JSON格式脚手架: 若想增加某个版本json脚手架,需要加入后缀如: 问题与解决方案: 1、问题: Your startup project \\\'XXX\\\' doesn\\\'t reference Microsoft.EntityFrameworkCore.Design. This package is requi

    2024年02月16日
    浏览(49)
  • 如果用上以下几种.NET EF Core性能调优,那么查询的性能会飙升

    1、避免在循环中进行查询操作: 避免在循环中进行查询操作,可以将查询结果缓存到内存中,然后对内存中的数据进行操作,可以提高性能。这种方式适合集合数据量少的数据,否则利大于弊。   2、避免使用懒加载: 避免使用懒加载,因为每次访问导航属性都会触发额外

    2024年02月02日
    浏览(37)
  • .NET6 + EF Core + MySQL 创建实体和数据库、EFCore 数据迁移

    接上期文章《.NET6项目连接数据库方式方法》,有人问了我几个问题,现在就这几个问题,拓展延申一下创建实体类、数据库。把ORM框架和数据迁移都写进去。 我的项目是在Linux上创建的,使用的是vscode开发工具远程开发。为了方便大家阅读和操作,我将项目down到我的本地电

    2024年02月05日
    浏览(50)
  • MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(3)-系统数据集合设计

    前几章教程我们把ToDoList系统的基本框架搭建好了,现在我们需要根据我们的需求把ToDoList系统所需要的系统集合(相当于关系型数据库中的数据库表)。接下来我们先简单概述一下这个系统主要需要实现的功能以及实现这些功能我们需要设计那些数据库集合。 MongoDB从入门到

    2024年02月21日
    浏览(39)
  • 4.1EF Core

    EF Core是微软官方的ORM框架,ORM即对象关系映射,也就是我们可以直接操作C#中的对象就可以完成数据库的操作。 EF Core环境搭建 首先要创建C#对象,用以对应数据库中的表,该C#对象也成为实体类。 根据所用的数据库选择NuGet包,本文使用SQLite数据库,所以安装Microsoft.EntityF

    2024年02月05日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包