Docs 菜单
Docs 主页
/ /

将MongoDB与实体框架和 ASP .NET Core 集成

在本指南中,您可以学习;了解如何创建 ASP .NET Core应用程序,该应用程序提供 OData 端点并使用实体框架 (EF) Core 提供程序访问权限MongoDB。 ASP .NET Core 是一个跨平台框架,用于创建基于云的应用程序。 OData 是用于构建和使用 RESTful API 的标准化协议,它允许您使用HTTP请求与数据进行交互。

本教程中的应用程序由以下各层组成:

  • 数据库层:MongoDB提供数据存储和检索。

  • 应用程序层:ASP .NET Core 处理HTTP请求、路由和依赖项注入。

  • 数据访问权限层:EF Core 提供程序提供MongoDB文档映射和 OData查询转换。

本教程使用 ASP .NET Core OData框架和适用于MongoDB 的实体框架 (EF) 核心提供程序来创建可查询的 REST API。 OData 提供了一种统一的数据公开和交互方式,并提供筛选、排序、分页和字段选择等高级查询功能。

通过将MongoDB与 ASP .NET Core 和 OData 集成,您可以使用 EF 熟悉的模式以及 MongoDB 灵活的文档模型和 OData查询功能。这种组合支持需要复杂查询接口、类型安全和基于标准的API设计的应用程序。您可以使用MongoDB、ASP .NET Core 和 OData 创建实际应用程序,例如数据分析仪表盘、报告系统或任何需要复杂数据查询的应用程序。

本教程向您展示如何构建使用MongoDB、ASP .NET Core 和 EF Core 提供程序的 OData REST API 。该应用程序访问示例餐厅数据,公开符合 OData 的端点,并支持筛选、排序、分页和字段选择等高级查询功能。本教程还包括连接到MongoDB Atlas上托管的MongoDB 集群的说明。

提示

如果更愿意使用 EF Core 提供程序而不使用 ASP .NET Core 连接到MongoDB ,请参阅 实体框架提供程序快速入门教程。

按照本节中的步骤安装项目依赖项,创建Atlas集群,并设立应用程序结构。

1

要创建快速入门应用程序,请在开发环境中安装以下软件:

先决条件
注意

安装.NET 8.0 或更高版本。

代码编辑器

使用您选择的代码编辑器。

终端应用和shell

对于Windows用户,请使用 PowerShell 或命令提示符。对于 macOS/ Linux用户,请使用终端或类似应用。

2

MongoDB Atlas是一项完全托管云数据库服务,用于托管MongoDB部署。如果您没有MongoDB 部署,可以通过完成MongoDB入门教程来免费创建MongoDB 集群。 MongoDB入门教程还演示了如何将示例数据集加载到集群中,包括本教程中使用的sample_restaurants 数据库。

要连接到MongoDB 集群,必须使用连接字符串。要学习;了解如何检索连接字符串,请参阅MongoDB入门教程的添加连接字符串部分。

重要

将连接string保存在安全位置。

3

从终端运行以下命令,创建一个名为 RestaurantODataApi 的新 ASP .NET Core Web API项目:

dotnet new webapi -n RestaurantODataApi
cd RestaurantODataApi
4

RestaurantODataApi目录中,运行以下命令以添加所需的 NuGet 包:

dotnet add package MongoDB.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.OData

这些命令安装以下软件包:

  • MongoDB.EntityFrameworkCore: MongoDB EF Core 提供程序

  • Microsoft.AspNetCore.OData:OData 对 ASP .NET Core 的支持

5

导航到 RestaurantODataApi项目中的 appsettings.json文件并粘贴以下代码:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"MongoDB": {
"ConnectionString": "<connection string>",
"DatabaseName": "sample_restaurants"
}
}

<connection string> 占位符替换为您从MongoDB入门教程中保存的连接字符串。

设置项目结构和依赖项后,请按照本节中的步骤创建数据模型、DbContext 和 OData 端点。

1

RestaurantODataApi目录中,创建 Models 子目录。然后,在 Models目录中创建名为 Restaurant.cs 的文件并添加以下代码:

RestaurantODataApi/Models/Restaurant.cs
using Microsoft.EntityFrameworkCore;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.ComponentModel.DataAnnotations;
namespace RestaurantODataApi.Models
{
public class Restaurant
{
[Key]
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; } = string.Empty;
[BsonElement("name")]
public string? Name { get; set; }
[BsonElement("cuisine")]
public string? Cuisine { get; set; }
[BsonElement("borough")]
public string? Borough { get; set; }
}
}

该模型类定义MongoDB sample_restaurants.restaurants集合中餐厅数据的结构,并包括实体框架和MongoDB序列化属性。

2

RestaurantODataApi目录中,创建名为 RestaurantDbContext.cs 的文件并添加以下代码:

RestaurantODataApi/RestaurantDbContext.cs
using Microsoft.EntityFrameworkCore;
using MongoDB.Driver;
using MongoDB.EntityFrameworkCore.Extensions;
using RestaurantODataApi.Models;
namespace RestaurantODataApi
{
public class RestaurantDbContext : DbContext
{
public DbSet<Restaurant> Restaurants { get; set; }
public RestaurantDbContext(DbContextOptions<RestaurantDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Configures the Restaurant entity to map to the "restaurants" collection
modelBuilder.Entity<Restaurant>().ToCollection("restaurants");
}
}
}

该类派生自 DBContext,用于配置模型与根本的数据库之间的关系。该代码将 EF 配置为与MongoDB配合使用,并将Restaurant 实体映射到sample_restaurants.restaurants 集合。

3

RestaurantODataApi目录中,创建 Controllers 子目录。然后,将名为 RestaurantsController.cs 的文件添加到子目录并粘贴以下代码:

RestaurantODataApi/Controllers/RestaurantsController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.Routing.Controllers;
using Microsoft.AspNetCore.OData.Routing.Attributes;
using RestaurantODataApi.Models;
namespace RestaurantODataApi.Controllers
{
public class RestaurantsController : ODataController
{
private readonly RestaurantDbContext _context;
public RestaurantsController(RestaurantDbContext context)
{
_context = context;
}
[EnableQuery(PageSize = 50, AllowedQueryOptions = AllowedQueryOptions.All)]
public IQueryable<Restaurant> Get()
{
return _context.Restaurants;
}
[HttpGet("odata/GetRestaurantsByBorough(borough={borough})")]
[EnableQuery(PageSize = 20)]
public IQueryable<Restaurant> GetRestaurantsByBorough(string borough)
{
return _context.Restaurants.Where(r => r.Borough == borough);
}
[HttpGet("odata/GetRestaurantsByCuisine(cuisine={cuisine})")]
[EnableQuery(PageSize = 20)]
public IQueryable<Restaurant> GetRestaurantsByCuisine(string cuisine)
{
return _context.Restaurants.Where(r => r.Cuisine == cuisine);
}
}
}

此控制器定义以下 OData REST 端点:

  • GET /odata/Restaurants:检索 restaurants集合中的所有文档。 EnableQuery 属性及其配置选项允许您在HTTP请求中使用 OData查询参数,例如 $filter$orderby

  • GET /odata/GetRestaurantsByBorough(borough='{borough}'):检索具有指定 borough 值的文档。

  • GET /odata/GetRestaurantsByCuisine(cuisine='{cuisine}'):检索具有指定 cuisine 值的文档。

4

导航到 Program.cs文件并将其内容替换为以下代码:

RestaurantODataApi/Program.cs
using Microsoft.AspNetCore.OData;
using Microsoft.EntityFrameworkCore;
using Microsoft.OData.ModelBuilder;
using MongoDB.Driver;
using RestaurantODataApi;
using RestaurantODataApi.Models;
var builder = WebApplication.CreateBuilder(args);
// Configures the MongoDB connection
var connectionString = builder.Configuration["MongoDB:ConnectionString"];
var databaseName = builder.Configuration["MongoDB:DatabaseName"] ?? "sample_restaurants";
if (string.IsNullOrEmpty(connectionString))
{
throw new InvalidOperationException("MongoDB connection string is required. Please set MongoDB:ConnectionString in appsettings.json");
}
// Registers a MongoDB client
builder.Services.AddSingleton<IMongoClient>(sp => new MongoClient(connectionString));
// Registers the DbContext
builder.Services.AddDbContext<RestaurantDbContext>(options =>
{
var mongoClient = new MongoClient(connectionString);
options.UseMongoDB(mongoClient, databaseName);
});
// Configures the OData EDM model
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Restaurant>("Restaurants");
modelBuilder.EntityType<Restaurant>().HasKey(r => r.Id);
// Registers the unbound functions
var getRestaurantsByBoroughFunction = modelBuilder.Function("GetRestaurantsByBorough");
getRestaurantsByBoroughFunction.Parameter<string>("borough");
getRestaurantsByBoroughFunction.ReturnsCollectionFromEntitySet<Restaurant>("Restaurants");
var getRestaurantsByCuisineFunction = modelBuilder.Function("GetRestaurantsByCuisine");
getRestaurantsByCuisineFunction.Parameter<string>("cuisine");
getRestaurantsByCuisineFunction.ReturnsCollectionFromEntitySet<Restaurant>("Restaurants");
// Configures OData with ASP.NET Core
builder.Services.AddControllers()
.AddOData(opt => opt
.AddRouteComponents("odata", modelBuilder.GetEdmModel())
.Select()
.Filter()
.OrderBy()
.Expand()
.Count()
.SetMaxTop(100));
var app = builder.Build();
app.UseRouting();
app.MapControllers();
app.Run();

此代码设置MongoDB连接、实体框架 DbContext 和 OData 服务。 OData 配置代码启用以下查询参数,您可以在HTTP端点中使用这些参数:

  • $select:返回结果中的指定字段

  • $filter:根据过滤条件返回数据

  • $orderby:按指定字段对结果进行排序

  • $expand:在结果中包含相关数据

  • $count:包括结果计数

  • $top:设置最大结果数,限制为 100

最后,按照本部分中的步骤运行OData REST API并使用HTTP请求测试端点。

1

RestaurantODataApi目录中,运行以下命令以编译并启动应用程序:

dotnet run

如果成功,命令输出将类似于以下示例:

info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5236
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
2

在另一个终端中,运行以下 curl 命令来测试 OData 端点。每个端点都返回 OData 格式的JSON数据,其中包括 sample_restaurants.restaurants集合中的餐厅信息。如果成功,您的 curl 命令将返回与所提供的示例输出类似的数据。这些命令还将结果限制为 5 个文档。

  1. 检索所有餐厅。

    curl 'http://localhost:5236/odata/Restaurants?$top=5'
    {"@odata.context":"http://localhost:5236/odata/$metadata#Restaurants",
    "value":[
    {"Id":"...","Name":"Riviera Caterer","Cuisine":
    "American","Borough":"Brooklyn","RestaurantId":"40356018"},
    {"Id":"...","Name":"Wilken'S Fine Food","Cuisine":
    "Delicatessen","Borough":"Brooklyn","RestaurantId":"40356483"},
    {"Id":"...","Name":"Kosher Island","Cuisine":
    "Jewish/Kosher","Borough":"Staten Island","RestaurantId":"40356442"},
    {"Id":"...","Name":"Wendy'S","Cuisine":"Hamburgers",
    "Borough":"Brooklyn","RestaurantId":"30112340"},
    {"Id":"...","Name":"Morris Park Bake Shop","Cuisine":
    "Bakery","Borough":"Bronx","RestaurantId":"30075445"}
    ]}
  2. 按行政区筛选餐厅。

    以下命令检索 borough 值为 "Queens" 的餐厅:

    curl 'http://localhost:5236/odata/GetRestaurantsByBorough(borough=%27Queens%27)?$top=5'
    {"@odata.context":"http://localhost:5236/odata/$metadata#Restaurants",
    "value":[
    {"Id":"...","Name":"Tov Kosher Kitchen","Cuisine":"Jewish/Kosher",
    "Borough":"Queens","RestaurantId":"40356068"},
    {"Id":"...","Name":"Brunos On The Boulevard","Cuisine":"American",
    "Borough":"Queens","RestaurantId":"40356151"},
    {"Id":"...","Name":"Carvel Ice Cream","Cuisine":"Ice Cream, Gelato, Yogurt, Ices",
    "Borough":"Queens","RestaurantId":"40361322"},
    {"Id":"...","Name":"Sal'S Deli","Cuisine":"Delicatessen",
    "Borough":"Queens","RestaurantId":"40361618"},
    {"Id":"...","Name":"Steve Chu'S Deli & Grocery","Cuisine":"Delicatessen",
    "Borough":"Queens","RestaurantId":"40361998"}
    ]}
  3. 按菜系筛选餐厅。

    以下命令检索 cuisine 值为 "Mexican" 的餐厅:

    curl 'http://localhost:5236/odata/GetRestaurantsByCuisine(cuisine=%27Mexican%27)?$top=5'
    {"@odata.context":"http://localhost:5236/odata/$metadata#Restaurants",
    "value":[
    {"Id":"...","Name":"Panchito'S","Cuisine":"Mexican","Borough":"Manhattan"},
    {"Id":"...","Name":"Mexico Lindo Restaurant","Cuisine":"Mexican","Borough":"Manhattan"},
    {"Id":"...","Name":"Casa Pepe","Cuisine":"Mexican","Borough":"Brooklyn"},
    {"Id":"...","Name":"Cuchifrito","Cuisine":"Mexican","Borough":"Manhattan"},
    {"Id":"...","Name":"Mary Ann'S","Cuisine":"Mexican","Borough":"Manhattan"}
    ]}
3

您可以通过包含 OData查询参数和操作符,使用端点运行复杂查询。以下 curl 命令测试这些功能。

  1. 按多个字段筛选。

    以下命令使用 OData查询运算符检索borough 值为 "Queens"name 值包含 "Moon" 的文档:

    curl 'http://localhost:5236/odata/Restaurants?$filter=Borough%20eq%20%27Queens%27%20and%20contains(Name,%20%27Moon%27)'
    {"@odata.context":"http://localhost:5236/odata/$metadata#Restaurants",
    "value":[
    {"Id":"...","Name":"New Moon Star Restaurant","Cuisine":"Chinese","Borough":"Queens"},
    {"Id":"...","Name":"Moon Tikka Grill","Cuisine":"Indian","Borough":"Queens"},
    {"Id":"...","Name":"Silver Moon Diner","Cuisine":"American","Borough":"Queens"},
    {"Id":"...","Name":"Mooney'S Public House","Cuisine":"Irish","Borough":"Queens"},
    {"Id":"...","Name":"Moon Light Crill Rest","Cuisine":"Indian","Borough":"Queens"},
    {"Id":"...","Name":"Full Moon Cafe","Cuisine":"Café/Coffee/Tea","Borough":"Queens"},
    {"Id":"...","Name":"Pacific Moon","Cuisine":"Chinese","Borough":"Queens"},
    {"Id":"...","Name":"Moon Palace Kitchen","Cuisine":"Chinese","Borough":"Queens"},
    {"Id":"...","Name":"Honey Moon Coffee Shop","Cuisine":"Café/Coffee/Tea","Borough":"Queens"},
    {"Id":"...","Name":"Honey Moon Coffee Shop","Cuisine":"Café/Coffee/Tea","Borough":"Queens"}
    ]}%
  2. 对结果进行排序和计数。

    以下命令按 name 值对与 cuisine 筛选器匹配的文档进行过滤,并计算匹配文档的总数:

    curl 'http://localhost:5236/odata/GetRestaurantsByCuisine(cuisine=%27Czech%27)?$orderby=Name&$count=true'
    {"@odata.context":"http://localhost:5236/odata/$metadata#Restaurants",
    "@odata.count":6,
    "value":[
    {"Id":"...","Name":"Bohemian Beer Garden","Cuisine":"Czech","Borough":"Queens"},
    {"Id":"...","Name":"Brooklyn Beet Company","Cuisine":"Czech","Borough":"Brooklyn"},
    {"Id":"...","Name":"Hospoda","Cuisine":"Czech","Borough":"Manhattan"},
    {"Id":"...","Name":"Koliba Restaurant","Cuisine":"Czech","Borough":"Queens"},
    {"Id":"...","Name":"Milan'S Restaurant","Cuisine":"Czech","Borough":"Brooklyn"},
    {"Id":"...","Name":"Olde Prague Tavern","Cuisine":"Czech","Borough":"Queens"}
    ]}

恭喜完成 EF、ASP .NET和 OData 快速入门教程!完成这些步骤后,您就拥有了一个 ASP .NET Core OData REST API ,它可以连接到MongoDB 部署,使用 OData 端点返回餐厅数据,并支持筛选、排序、分页、字段选择和搜索等高级查询功能。

要学习;了解有关本教程中提到的概念的更多信息,请参阅以下资源:

后退

兼容性

在此页面上