C#(C Sharp)使用 .NET 7、ASP.NET、Entity Framework、Postgres、Docker 和 Docker Compose 的 CRUD Rest API

2025-06-05

C#(C Sharp)使用 .NET 7、ASP.NET、Entity Framework、Postgres、Docker 和 Docker Compose 的 CRUD Rest API

让我们使用 C#(或 C sharp)创建一个 CRUD Rest API,使用:

  • .NET 7
  • ASP.NET(构建 Web 应用程序的框架)
  • 实体框架(ORM)
  • Postgres(数据库)
  • Docker(容器化)
  • Docker Compose(运行数据库和应用程序)

视频版本:

所有代码均可在 GitHub 存储库中找到(视频描述中的链接):https://youtube.com/live/PY6uD1fgzZA


🏁 简介

以下是我们要创建的应用程序架构图:

对 ASP.NET(C# 标识)和 Postgres 服务进行 crud、read、update、delete 操作,并通过 Docker Compose 连接。使用 Postman 和 Tableplus 进行测试

我们将为基本的 CRUD 操作创建 5 个端点:

  • 创造
  • 阅读全部
  • 阅读一篇
  • 更新
  • 删除

以下是我们正在采取的步骤:

  1. 定义需求
  2. 创建新的 C# 项目
  3. 安装依赖项
  4. 配置数据库连接
  5. 创建 CRUD 操作的逻辑
  6. 更新项目
  7. Dockerfile
  8. docker-compose.yml
  9. 运行 Postgres 数据库和应用程序
  10. 更新数据库架构
  11. 测试应用程序

我们将提供一步一步的指南,以便您可以跟随。


📋 要求:

  • .NET 7 已安装并正在运行
  • dotnet CLI
  • (可选):VS Code 的 C# 扩展包 ___ ## 🚀 创建一个新的 C# 项目

创建新的 C# 项目有很多方法,但我将使用 dotnet CLI

打开终端并运行以下命令:



dotnet new webapi -n csharp-crud-api


Enter fullscreen mode Exit fullscreen mode

现在进入目录:



cd csharp-crud-api


Enter fullscreen mode Exit fullscreen mode

📦安装依赖项

我们将使用以下依赖项:

  • 实体框架
  • Npgsql(Postgres 驱动程序)

要安装它们,请确保在csharp-crud-api目录中并运行以下命令:



dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL


Enter fullscreen mode Exit fullscreen mode

🔍 测试基础应用程序

在我们继续之前,让我们看看项目是否配置正确。

在 VS Code(或您最喜欢的 IDE)中打开该文件夹。



code .


Enter fullscreen mode Exit fullscreen mode

您应该看到以下结构:

C# 项目的结构

现在运行以下命令来启动应用程序:



dotnet run --urls=http://localhost:5000


Enter fullscreen mode Exit fullscreen mode

您应该看到以下输出:

dotnet run 命令的输出

要测试应用程序,请打开浏览器并转到以下 URL:http://localhost:5000/weatherforecast

您应该看到以下输出:

获取天气响应

现在是时候开始编写应用程序代码了。


📝 编写应用程序代码

编写应用程序有三个步骤:

  • 配置数据库连接
  • 创建 CRUD 操作的逻辑
  • 更新Program.cs文件

🗄️配置数据库连接

打开appsettings.json文件并添加以下行:



{
  "ConnectionStrings": {
    "DefaultConnection": "Host=db;Port=5432;Database=postgres;Username=postgres;Password=postgres"
  }
}


Enter fullscreen mode Exit fullscreen mode

您的appsettings.json文件应如下所示:



{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Host=db;Port=5432;Database=postgres;Username=postgres;Password=postgres"
  }
}


Enter fullscreen mode Exit fullscreen mode

✏️ 创建 CRUD 操作的逻辑

创建一个名为 的新文件夹,并在其中Models创建一个名为 的新文件。User.cs

C# 项目的结构

填充User.cs以下代码:



using System.ComponentModel.DataAnnotations.Schema;

namespace Models
{
    [Table("users")]
    public class User
    {
        [Column("id")]
        public int Id { get; set; }

        [Column("name")]
        public string Name { get; set; }

        [Column("email")]
        public string Email { get; set; }
    }
}


Enter fullscreen mode Exit fullscreen mode

现在创建一个名为 的新文件夹,并在其中Data创建一个名为 的新文件。UserContext.cs

UserContext.cs使用以下代码填充文件:



using Models;
using Microsoft.EntityFrameworkCore;

namespace Data
{
    public class UserContext : DbContext
    {
        public UserContext(DbContextOptions<UserContext> options) : base(options)
        {
        }

        public DbSet<User> Users { get; set; }
    }
}


Enter fullscreen mode Exit fullscreen mode

现在创建一个名为 的新文件夹,并在其中Controllers创建一个名为 的新文件。UsersController.cs

UserscController.cs使用以下代码填充文件:



using Data;
using Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace csharp_crud_api.Controllers;


[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
  private readonly UserContext _context;

  public UsersController(UserContext context)
  {
    _context = context;
  }

  // GET: api/users
  [HttpGet]
  public async Task<ActionResult<IEnumerable<User>>> GetUsers()
  {
    return await _context.Users.ToListAsync();
  }

  // GET: api/users/5
  [HttpGet("{id}")]
  public async Task<ActionResult<User>> GetUser(int id)
  {
    var user = await _context.Users.FindAsync(id);

    if (user == null)
    {
      return NotFound();
    }

    return user;
  }

  // POST: api/users
  [HttpPost]
  public async Task<ActionResult<User>> PostUser(User user)
  {
    _context.Users.Add(user);
    await _context.SaveChangesAsync();

    return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
  }

  // PUT: api/users/5
  [HttpPut("{id}")]
  public async Task<IActionResult> PutUser(int id, User user)
  {
    if (id != user.Id)
    {
      return BadRequest();
    }

    _context.Entry(user).State = EntityState.Modified;

    try
    {
      await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
      if (!UserExists(id))
      {
        return NotFound();
      }
      else
      {
        throw;
      }
    }

    return NoContent();
  }

  // DELETE: api/users/5
  [HttpDelete("{id}")]
  public async Task<IActionResult> DeleteUser(int id)
  {
    var user = await _context.Users.FindAsync(id);
    if (user == null)
    {
      return NotFound();
    }

    _context.Users.Remove(user);
    await _context.SaveChangesAsync();

    return NoContent();
  }

  private bool UserExists(int id)
  {
    return _context.Users.Any(e => e.Id == id);
  }

  // dummy method to test the connection
  [HttpGet("hello")]
  public string Test()
  {
    return "Hello World!";
  }
}


Enter fullscreen mode Exit fullscreen mode

🖋️ 更新Program.cs文件

我们快完成了,现在我们只需要更新Program.cs文件。

在文件顶部添加这两个导入:



using Data;
using Microsoft.EntityFrameworkCore;


Enter fullscreen mode Exit fullscreen mode

并且这些行位于var app = builder.Build();行上方:



// Added configuration for PostgreSQL
var configuration = builder.Configuration;
builder.Services.AddDbContext<UserContext>(options =>
    options.UseNpgsql(configuration.GetConnectionString("DefaultConnection")));


Enter fullscreen mode Exit fullscreen mode

Program.cs或者您可以用以下代码替换整个文件:



using Data;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Added configuration for PostgreSQL
var configuration = builder.Configuration;
builder.Services.AddDbContext<UserContext>(options =>
    options.UseNpgsql(configuration.GetConnectionString("DefaultConnection")));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();


Enter fullscreen mode Exit fullscreen mode

我们已经完成了应用程序逻辑,现在是时候对其进行 Docker 化了。


🐳 Docker 化应用程序

我们将通过创建和填充两个文件来 Docker 化该应用程序:

  • Dockerfile
  • docker-compose.yml

🐋 Dockerfile

在项目的根目录下创建一个名为的新文件Dockerfile,并用以下代码填充它:



FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /app

COPY *.csproj ./
RUN dotnet restore

COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS runtime
WORKDIR /app
COPY --from=build /app/out ./

ENTRYPOINT ["dotnet", "csharp-crud-api.dll"]


Enter fullscreen mode Exit fullscreen mode

解释:

Dockerfile 中有两个阶段,buildruntime

构建阶段:

  • FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build:此行告诉 Docker 使用该mcr.microsoft.com/dotnet/sdk:7.0映像作为构建阶段的基础映像。
  • WORKDIR /app:此行告诉 Docker 将工作目录设置为/app
  • COPY *.csproj ./:此行告诉 Docker 将所有.csproj文件复制到工作目录。
  • RUN dotnet restore:此行告诉 Docker 运行dotnet restore命令。
  • COPY . ./:此行告诉 Docker 将所有文件复制到工作目录。
  • RUN dotnet publish -c Release -o out:此行告诉 Docker 运行dotnet publish命令。

运行时阶段:
此阶段与构建阶段非常相似,唯一的区别是我们使用mcr.microsoft.com/dotnet/aspnet:7.0图像作为基础图像。

  • FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS runtime:此行告诉 Docker 使用该mcr.microsoft.com/dotnet/aspnet:7.0映像作为运行时阶段的基础映像。
  • WORKDIR /app:此行告诉 Docker 将工作目录设置为/app
  • COPY --from=build /app/out ./:此行告诉 Docker 将out文件夹从构建阶段复制到工作目录。
  • ENTRYPOINT ["dotnet", "csharp-crud-api.dll"]:此行告诉 Docker 运行dotnet csharp-crud-api.dll命令。

🐙 docker-compose.yml

在项目的根目录下创建一个名为的新文件docker-compose.yml,并用以下代码填充它:



version: '3'
services:
  csharp_app:
    container_name: csharp_app
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:80"
    depends_on:
      - db
    environment:
      ConnectionStrings__DefaultConnection: "Host=db;Database=postgres;Username=postgres;Password=postgres"
  db:
    container_name: db
    image: postgres:12
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=postgres
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata: {}


Enter fullscreen mode Exit fullscreen mode

解释:

解释:

  • 我们定义了两个服务:csharp_appdb​​ .Csharp_app:
  • container_name: csharp_app:这一行告诉 Docker 命名容器csharp_app
  • build::此行告诉 Docker 从 构建映像Dockerfile
  • ports:8080:这一行告诉Docker将容器的端口暴露给80主机的端口。
  • depends_on::这一行告诉Docker该csharp_app容器依赖于该db容器。
  • environment::此行告诉 Docker 为设置环境变量ConnectionStrings__DefaultConnection

数据库:

  • container_name: db:这一行告诉 Docker 命名容器db
  • image: postgres:12:此行告诉 Docker 使用该postgres:12图像作为容器的基础图像。
  • environment:POSTGRES_USER:此行告诉 Docker 为、POSTGRES_PASSWORD设定环境变量POSTGRES_DB
  • ports:5432:这一行告诉Docker将容器的端口暴露给5432主机的端口。
  • volumes::此行告诉 Docker 将pgdata卷挂载到/var/lib/postgresql/data容器的目录中。

我们还需要定义容器pgdata使用的体积db

大功告成!现在我们可以运行 Postgres 和应用程序容器了。


🏃‍♂️ 运行应用程序

我们将运行文件中定义的容器(服务)docker-compose.yml

🐘 运行 Postgres 容器



docker compose up -d db


Enter fullscreen mode Exit fullscreen mode

📜 在数据库中创建表

我们可以用不同的方式创建表,但让我向您展示如何直接从应用程序容器中执行此操作。

首先,确保 Postgres 容器正在运行。

打开不同的终端并运行以下命令:



docker exec -it db psql -U postgres


Enter fullscreen mode Exit fullscreen mode

现在我们已经进入了 Postgres 容器。我们可以使用以下命令创建表:



CREATE TABLE "users" (
  "id" SERIAL PRIMARY KEY,
  "name" VARCHAR(50) NOT NULL,
  "email" VARCHAR(255) NOT NULL
);


Enter fullscreen mode Exit fullscreen mode

🏗️ 构建并运行应用程序容器

构建 Docker 镜像:



docker compose build


Enter fullscreen mode Exit fullscreen mode

运行应用程序容器:



docker compose up csharp_app


Enter fullscreen mode Exit fullscreen mode

🧪 测试应用程序

让我们用 Postman 测试应用程序

现在我们可以测试项目了。我们将使用 Postman,但您也可以使用任何其他工具。

📝 创建用户

要创建新用户,请创建一个POST request to localhost:8080/api/users

请求主体应该是这样的:



{
    "name": "aaa",
    "email": "aaa@mail"
}


Enter fullscreen mode Exit fullscreen mode

输出应该是这样的:

创建用户

让我们再创建两个用户,创建一个POST request to localhost:8080/api/users



{
    "name": "bbb",
    "email": "bbb@mail"
}


Enter fullscreen mode Exit fullscreen mode


{
    "name": "ccc",
    "email": "ccc@mail"
}


Enter fullscreen mode Exit fullscreen mode

📝 获取所有用户

要获取所有用户,请创建一个GET request to localhost:8000/api/users

输出应该是这样的:

获取所有用户

📝 获取用户

要获得用户,请创建一个GET request to localhost:8000/api/users/{id}

例如GET request to localhost:8000/api/users/1

输出应该是这样的:

获取用户

📝 更新用户

要更新用户,请制作PUT request to localhost:8000/api/users/{id}

例如PUT request to localhost:8000/api/users/2

请求主体应该是这样的:



{
    "name": "Francesco",
    "email": "francesco@mail"
}


Enter fullscreen mode Exit fullscreen mode

输出应该是这样的:

更新用户

📝 删除用户

要删除用户,请创建一个DELETE request to localhost:8000/api/users/{id}

例如DELETE request to localhost:8000/api/users/1

在 Postman 上你应该会看到类似这样的内容:

删除用户

最终测试

作为最后的测试,我们可以使用 TablePlus 检查数据库。

表格加


🏁结论

我们成功了!我们用 C#(或 C sharp)构建了一个 CRUD Rest API 项目,使用:

  • .NET 7
  • ASP.NET(构建 Web 应用程序的框架)
  • 实体框架(ORM)
  • Postgres(数据库)
  • Docker(容器化)
  • Docker Compose(运行数据库和应用程序)

视频版本:

所有代码均可在 GitHub 存储库中找到(视频描述中的链接):https://youtube.com/live/PY6uD1fgzZA

就这样。

如果您有任何疑问,请在下面发表评论。

弗朗西斯科

文章来源:https://dev.to/francescoxx/cc-sharp-crud-rest-api-using-net-7-aspnet-entity-framework-postgres-docker-and-docker-compose-493a
PREV
熟悉 Rust 的语法
NEXT
你不知道自己需要的 CSS 属性