Overview
在本指南中,您可以学习;了解如何创建 ASP .NET Core 应用程序,该应用程序提供 OData 端点并使用 实体框架 (EF) Core 提供程序 访问权限 MongoDB。ASP .NET Core 是一个跨平台框架,用于创建基于云的应用程序。OData 是用于构建和使用 RESTful API 的标准化协议,它允许您使用 HTTP 请求与数据进行交互。
本教程中的应用程序由以下各层组成:
数据库层:MongoDB提供数据存储和检索。
应用程序层:ASP .NET Core 处理HTTP请求、路由和依赖项注入。
数据访问层:EF Core 提供商提供MongoDB文档映射和 OData查询转换。
为何将MongoDB与 ASP .NET Core 和 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集群,并设立应用程序结构。
配置数据库连接。
导航到 RestaurantODataApi项目中的 appsettings.json文件并粘贴以下代码:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "MongoDB": { "ConnectionString": "<connection string>", "DatabaseName": "sample_restaurants" }}将 <connection string> 占位符替换为您从MongoDB入门教程中保存的连接字符串。
创建应用程序
设置项目结构和依赖项后,请按照本节中的步骤创建数据模型、DbContext 和 OData 终结点。
创建数据模型。
在 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序列化属性。
配置数据库连接。
在 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集合。
创建 OData 控制器。
在 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值的文档。
定义应用程序逻辑。
导航到 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 connectionvar 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 clientbuilder.Services.AddSingleton<IMongoClient>(sp => new MongoClient(connectionString));
// Registers the DbContextbuilder.Services.AddDbContext<RestaurantDbContext>(options =>{ var mongoClient = new MongoClient(connectionString); options.UseMongoDB(mongoClient, databaseName);});
// Configures the OData EDM modelvar modelBuilder = new ODataConventionModelBuilder();modelBuilder.EntitySet<Restaurant>("Restaurants");modelBuilder.EntityType<Restaurant>().HasKey(r => r.Id);
// Registers the unbound functionsvar 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 Corebuilder.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请求测试终结点。
测试您的 OData 终结点。
在另一个终端中,运行以下 curl 命令来测试 OData 终结点。每个终结点都返回 OData 格式的JSON数据,其中包括 sample_restaurants.restaurants集合中的餐厅信息。如果成功,您的 curl 命令将返回与所提供的示例输出类似的数据。这些命令还将结果限制为 5 个文档。
检索所有餐厅。
curl 'http://localhost:5236/odata/Restaurants?$top=5'按行政区筛选餐厅。
以下命令检索
borough值为"Queens"的餐厅:curl 'http://localhost:5236/odata/GetRestaurantsByBorough(borough=%27Queens%27)?$top=5'按菜系筛选餐厅。
以下命令检索
cuisine值为"Mexican"的餐厅:curl 'http://localhost:5236/odata/GetRestaurantsByCuisine(cuisine=%27Mexican%27)?$top=5'
测试 OData 的高级查询功能。
您可以通过包含 OData查询参数和操作符,使用终结点运行复杂查询。以下 curl 命令测试这些功能。
按多个字段筛选。
以下命令使用 OData查询运算符检索
borough值为"Queens"且name值包含"Moon"的文档:curl 'http://localhost:5236/odata/Restaurants?$filter=Borough%20eq%20%27Queens%27%20and%20contains(Name,%20%27Moon%27)'对结果进行排序和计数。
以下命令按
name值对与cuisine筛选器匹配的文档进行过滤,并计算匹配文档的总数:curl 'http://localhost:5236/odata/GetRestaurantsByCuisine(cuisine=%27Czech%27)?$orderby=Name&$count=true'
恭喜完成 EF、ASP .NET和 OData 快速入门教程!完成这些步骤后,您就拥有了一个 ASP .NET Core OData REST API ,它可以连接到MongoDB 部署,使用 OData 终结点返回餐厅数据,并支持筛选器、排序、分页、字段选择和搜索等高级查询功能。
其他资源
要学习;了解有关本教程中提到的概念的更多信息,请参阅以下资源:
OData 协议 文档