原文 | Rishit, Luce

翻译 | 郑子铭

这是 Rishit Bhatia 和 Luce Carter 的客座文章。Rishit 是 MongoDB 的高级产品经理,专注于 .NET 开发人员体验,在进入产品管理部门之前,他已经使用 C# 工作多年。Luce 是 MongoDB 的开发倡导者、Microsoft MVP,热爱代码、阳光和学习。本博客由 Microsoft .NET 团队针对 EF Core 进行了审阅。

MongoDB 的 EF Core 提供程序于 2024 年 5 月正式发布。自六个月前首次发布此软件包的预览版以来,我们已经取得了长足的进步。我们想分享一些我们一直在研究的有趣功能,如果没有 Microsoft .NET 数据和实体框架团队的支持和合作,这些功能是不可能实现的。

在这篇文章中,我们将使用 MongoDB EF Core 提供程序MongoDB Atlas 来展示以下内容:

  • 向实体添加属性并进行更改跟踪
  • 利用出口创建索引
  • 执行复杂查询
  • 事务和乐观并发

与本博客相关的代码可以在 Github 上找到。入门样板代码位于“start”分支中。包含下面提到的所有功能亮点的完整代码位于“main”分支中。

先决条件

我们将使用示例数据集 — 具体来说,本示例中 MongoDB Atlas 可用的 sample_mflix 数据库中的电影集合。要使用示例数据设置 Atlas 集群,您可以按照文档中的步骤操作。我们将创建一个简单的 .NET 控制台应用程序来开始使用 MongoDB EF Core 提供程序。有关如何执行此操作的更多详细信息,您可以查看快速入门指南

此时,您应该已连接到 Atlas 并能够从快速入门指南中正在读取的电影中输出电影情节。

功能亮点

添加属性和更改跟踪

MongoDB 文档模型的优点之一是它支持灵活的架构。再加上 EF Core 支持 Code First 方法的能力,您可以动态向实体添加属性。为了展示这一点,我们将向我们的模型类添加一个名为 adapted_from_book 的新可空布尔属性。这将使我们的模型类如下所示:

public class Movie
{
public ObjectId Id { get; set; } [BsonElement("title")]
public string Title { get; set; } [BsonElement("rated")]
public string Rated { get; set; } [BsonElement("plot")]
public string Plot { get; set; } [BsonElement("adaptedFromBook")]
public bool? AdaptedFromBook { get; set; }
}

现在,我们将为找到的电影实体设置这个新添加的属性,并在保存更改后查看 EF Core 的更改跟踪功能。为此,我们将在打印电影情节后添加以下代码行:

movie.AdaptedFromBook = false;
await db.SaveChangesAsync();

在运行程序之前,让我们转到 Atlas 中的集合并找到这部电影,以确保这个新创建的字段 adapted_from_book 不存在于我们的数据库中。为此,只需转到 Atlas Web UI 中的集群并选择浏览集合。

然后,从 sample_mflix 数据库中选择电影集合。在过滤器选项卡中,我们可以使用以下查询找到我们的电影:

{title: "Back to the Future"}

这应该可以找到我们的电影,并且我们可以确认我们想要添加的新字段确实没有被看到。

接下来,让我们在刚刚添加的两行代码中添加一个断点,以确保我们可以在继续操作时实时跟踪更改。选择“开始调试”按钮来运行应用程序。当第一个断点被击中时,我们可以看到本地字段值已被分配。

让我们点击“继续”并检查数据库中的文档。我们可以看到新字段尚未添加。让我们跳过将结束程序的“保存更改”调用。此时,如果我们检查数据库中的文档,我们会注意到新字段已添加,如下所示!

索引管理

MongoDB EF Core 提供程序建立在现有的 .NET/C# 驱动程序之上。此架构的一个优点是,我们可以重用已为 DbContext 创建的 MongoClient,以利用 MongoDB 开发人员数据平台公开的其他功能。这包括但不限于索引管理Atlas 搜索矢量搜索等功能。

我们将了解如何在同一个应用程序中使用驱动程序创建新索引。首先,我们将列出集合中的索引,以查看哪些索引已经存在。MongoDB 默认在 _id 字段上创建索引。我们将创建一个辅助函数来打印索引:

var moviesCollection = client.GetDatabase("sample_mflix").GetCollection<Movie>("movies");
Console.WriteLine("Before creating a new Index:");
PrintIndexes(); void PrintIndexes()
{
var indexes = moviesCollection.Indexes.List();
foreach (var index in indexes.ToList())
{
Console.WriteLine(index);
}
}

预期输出如下所示:

{ "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" }

现在,我们将在我们的集合中的标题和评级字段上创建一个复合索引,并再次打印索引。

var moviesIndex = new CreateIndexModel<Movie>(Builders<Movie>.IndexKeys
.Ascending(m => m.Title)
.Ascending(x => x.Rated));
await moviesCollection.Indexes.CreateOneAsync(moviesIndex); Console.WriteLine("After creating a new Index:");
PrintIndexes();

我们可以看到,一个名为title_1_rated_1的新索引已经创建。

After creating a new Index:
{ "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" }
{ "v" : 2, "key" : { "title" : 1, "rated" : 1 }, "name" : "title_1_rated_1" }

查询数据

由于 EF Core 已经支持语言集成查询 (LINQ) 语法,因此使用 C# 编写强类型查询变得很容易。根据模型类中可用的字段,我们可以尝试从我们的收藏中查找一些有趣的电影。假设我想查找所有评级为“PG-13”且情节包含单词“shark”的电影,但我希望按标题字段对它们进行排序。我可以使用以下查询轻松完成此操作:

var myMovies = await db.Movies
.Where(m => m.Rated == "PG-13" && m.Plot.Contains("shark"))
.OrderBy(m => m.Title)
.ToListAsync(); foreach (var m in myMovies)
{
Console.WriteLine(m.Title);
}

然后,我们可以使用上面的代码打印出查询,并使用 dotnet run 运行程序以查看结果。我们应该能够在控制台中看到我们收藏的 20K+ 部电影中的两部电影名称,如下所示。

Jaws: The Revenge
Shark Night 3D

如果您想查看发送到服务器的查询(在本例中为 MQL),那么您可以在 DbContext 上的 Create 函数中启用日志记录,如下所示:

   public static MflixDbContext Create(IMongoDatabase database) =>
new(new DbContextOptionsBuilder<MflixDbContext>()
.UseMongoDB(database.Client, database.DatabaseNamespace.DatabaseName)
.LogTo(Console.WriteLine)
.EnableSensitiveDataLogging()
.Options);

这样,当我们再次运行程序时,我们就可以看到以下内容作为详细日志的一部分:

Executed MQL query
sample_mflix.movies.aggregate([{ "$match" : { "rated" : "PG-13", "plot" : /shark/s } }, { "$sort" : { "title" : 1 } }])

自动事务和乐观并发

是的,你没看错!MongoDB EF Core 提供程序从其 8.1.0 版本开始支持事务和乐观并发。这意味着默认情况下,SaveChangesSaveChangesAsync 是事务性的。这将使生产级工作负载中的操作在发生任何故障时自动回滚,并确保所有操作都以乐观并发的方式完成。

如果您想关闭事务,您可以在调用任何 SaveChanges 操作之前的初始化阶段进行关闭。

db.Database.AutoTransactionBehavior = AutoTransactionBehavior.Never;

根据您的需求,提供程序支持两种乐观并发方法,即通过并发检查或行版本。您可以在文档中阅读更多相关信息。我们将使用 RowVersion 来演示此用例。这将利用模型类中的 Version 字段,该字段将由 MongoDB EF 提供程序自动更新。要添加版本,我们将以下内容添加到模型类中。

 [Timestamp]
public long? Version { get; set; }

首先,让我们创建一个名为 myMovie 的新电影实体,如下所示,并将其添加到 DbSet,然后添加 SaveChangesAsync

Movie myMovie1= new Movie {
Title = "The Rise of EF Core 1",
Plot = "Entity Framework (EF) Core is a lightweight, extensible, open source and cross-platform version of the popular Entity Framework data access technology.",
Rated = "G"
}; db.Movies.Add(myMovie1);
await db.SaveChangesAsync();

现在,让我们创建一个类似于上面创建的 DbContext 的新 DbContext。我们可以将数据库创建移到变量中,这样我们就不必再次定义数据库的名称。有了这个新上下文,让我们为电影添加续集并将其添加到 DbSet。我们还将添加第三部分(是的,这是三部曲),但使用与第二部电影实体相同的 ID 到这个新上下文,然后保存我们的更改。

var dbContext2 = MflixDbContext.Create(database);
dbContext2.Database.AutoTransactionBehavior = AutoTransactionBehavior.Never;
var myMovie2 = new Movie { title = "The Rise of EF Core 2" };
dbContext2.Movies.Add(myMovie2); var myMovie3 = new Movie { Id = myMovie2.Id,Title = "The Rise of EF Core 3" };
dbContext2.Movies.Add(myMovie3);
await dbContext2.SaveChangesAsync();

现在支持事务了,对于后两个电影实体的第二组操作不应该通过,因为我们试图用已经存在的 _id 添加它们。我们应该看到一个异常,事务应该只在我们的数据库中看到一部电影。让我们运行一下,看看这是否属实。

我们正确地看到了一个异常,我们可以确认我们只有一部电影(第一部分)插入了数据库。

由于事务已回滚,以下仅显示数据库中的单个文档。

别担心,我们会正确地将我们的三部曲添加到数据库中。让我们删除第三个实体上的 _id 分配,让 MongoDB 自动为我们插入它。

var myMovie3 = new Movie { Title = "The Rise of EF Core 3" };

一旦我们重新运行该程序,我们可以看到所有实体都已添加到数据库中。

摘要

我们能够使用 MongoDB EF Core 提供程序MongoDB Atlas 来展示不同的功能,例如动态向实体添加属性、利用 Escape Hatch 创建索引、通过 LINQ 执行复杂查询以及演示新添加的事务和乐观并发支持。

了解更多

要了解有关 EF Core 和 MongoDB 的更多信息:

原文链接

MongoDB EF Core Provider: What’s New?

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com)

【译】MongoDB EF Core 提供程序:有什么新功能?的更多相关文章

  1. [翻译 EF Core in Action 1.6]你的第一个EF Core应用程序

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

  2. TDengine 时序数据库的 ADO.Net Core 提供程序 Maikebing.EntityFrameworkCore.Taos

    简介 Entity, Framework, EF, Core, Data, O/RM, entity-framework-core,TDengine Maikebing.Data.Taos 是一个基于 ...

  3. 【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  4. [转]【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  5. [译] OpenStack Pike 版本中的 53 个新功能盘点

      原文:https://www.mirantis.com/blog/53-things-to-look-for-in-openstack-pike/ 作者:Mirantis Nick Chase 发 ...

  6. [译] OpenStack Ocata 版本中的 53 个新功能盘点

    原文链接:https://www.mirantis.com/blog/53-new-things-to-look-for-in-openstack-ocata/ 原文作者:Nick Chase, Ra ...

  7. 微信小程序开发平台新功能「云开发」快速上手体验

    微信小程序开发平台刚刚开放了一个全新的功能:云开发. 简单地说就是将开发人员搭建微信小程序后端的成本再次降低,此文刚好在此产品公测时,来快速上手看看都有哪些方便开发者的功能更新. 微信小程序一直保持一 ...

  8. 微软正式发布VS2015和.Net为开发者提供数百个新功能

    今天,我很高兴地向大家宣布:Visual Studio 2015 和 .Net 4.6 的正式版本现已提供下载! 自去年十一月我们提出了微软开发技术的愿景:让所有开发者,无论他在什么平台,开发哪种应用 ...

  9. 一步步学习EF Core(3.EF Core2.0路线图)

    前言 这几天一直在研究EF Core的官方文档,暂时没有发现什么比较新的和EF6.x差距比较大的东西. 不过我倒是发现了EF Core的路线图更新了,下面我们就来看看 今天我们来看看最新的EF Cor ...

  10. 深入理解 EF Core:使用查询过滤器实现数据软删除

    原文:https://bit.ly/2Cy3J5f 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能会去除一些本人实在不知道如何组织 ...

随机推荐

  1. 从2s优化到0.1s

    前言 分类树查询功能,在各个业务系统中可以说随处可见,特别是在电商系统中. 但就是这样一个简单的分类树查询功能,我们却优化了5次. 到底是怎么回事呢? 背景 我们的网站使用了SpringBoot推荐的 ...

  2. STATA数据统计软件学习记录

    STATA是一个数据统计软件,正如它的名字一样,STATA=statistic+data.STATA软件的功能和matlab类似,也可以用代码实现数据的统计与可视化.但几乎只能进行整行整列的数据处理, ...

  3. Memcached笔记——(一)安装&常规错误&监控

    08年的时候接触过Memcached,当时还对它的客户端产品嗤之以鼻,毕竟手工代码没有各种ORM原生XML配置方便.尽管如此,Memcached现在已经成了服务器架构里不可或缺的一部分! 相关链接:  ...

  4. SSD:清华出品,可切换密集稀疏的大模型预训练加速方案 | ICML'24

    来源:晓飞的算法工程笔记 公众号,转载请注明出处 论文: Exploring the Benefit of Activation Sparsity in Pre-training 论文地址:https ...

  5. 强网杯2023 谍影重重2.0 wp

    题目描述 小明是某间谍组织的一员,他终日监听着我国某重点军事基地的飞行动态,妄图通过分析参数找到我国飞的最快的飞机.我国费尽千辛万苦抓住了他,并在他的电脑上找到了一段他监听的信息,请分析出这段信息中飞 ...

  6. uniapp多次触发跳转问题

    问题描述:快速点击跳转页面后会闪退到登陆页面 解决方案:重新封装uniapp跳转api,加防抖锁,To.ts import { NavigateToOptions, RedirectToOptions ...

  7. Element Plus组件el-select回显异常

    前情 公司有经常需要做一些后台管理页面,我们选择了Element Plus,它是基于 Vue 3,面向设计师和开发者的组件库,是Vue框架生态中比较火的UI组件库,组件库丰富易用,组件链接:一个 Vu ...

  8. C/C++源码扫描系列- Joern 篇

    文章首发于 https://xz.aliyun.com/t/9277 概述 和 codeql,Fortify 相比 Joern不需要编译源码即可进行扫描,适用场景和环境搭建方面更加简单. 环境搭建 首 ...

  9. Nvidia Jetson Xavier NX安装GPU版pytorch与torchvision

    前提是已经安装好了系统,并通过JetPack配置完了cuda.cudnn.conda等库. 1. 安装GPU版pytorch 在base环境上新建环境,python版本3.8,激活并进入. conda ...

  10. Element Plus组件库el-select组件多选回显踩坑

    前情 公司有经常需要做一些后台管理页面,我们选择了Element Plus,它是基于 Vue 3,面向设计师和开发者的组件库,是Vue框架生态中比较火的UI组件库,组件库丰富易用,组件链接:一个 Vu ...