笔记:如何使用 Entity Framework Core

news/2026/1/21 17:22:03/文章来源:https://www.cnblogs.com/abaiami/p/19513059

前言

在本篇文章中,着重介绍如何使用 Entity Framework Core,不过多涉及底层细节。

Entity Framework Core(简称 EF Core)是微软为.NET 平台打造的轻量级、跨平台对象关系映射(ORM)框架,以编写 C# 对象代码的方式操作各类数据库,无需大量手写原生 SQL 语句。

其中有两大概念,也是本文要讲述的内容:

  • DbContext 配置和初始化
  • 模型的创建与使用

DbContext

DbContext 是 EF Core 中连接 C# 代码与数据库的核心桥梁类(需要继承 EF Core 的 DbContext 基类自定义),所有对数据库的增删改查操作,都必须通过它来完成。

它的核心作用可以概括为 3 点:

  1. 管理数据库连接:自动处理和数据库的连接建立、释放,无需你手动写连接代码;
  2. 提供表操作入口:通过 DbSet<T> 属性(比如 DbSet<User>)对应数据库的一张表,是操作表的唯一入口;
  3. 翻译与执行:把对 C# 实体类的 LINQ 操作(比如 Add 新增、Where 查询)自动转换成 SQL 语句,提交到数据库执行。

DbSet<T> 是 EF Core 提供的泛型集合类型,泛型参数 T 必须是定义的实体类

模型

EF Core 里的 “模型”,本质是程序中所有实体类、实体间关系,以及这些实体与数据库表 / 字段映射规则的整体描述

它的核心作用可以概括为两点:

  1. 是 EF Core 的认知基础:EF Core 只有先通过模型知道 “User 类对应 Users 表、Id 属性对应主键字段、一个用户对应多个商品”,才能正确把 C# 操作(比如新增用户)翻译成对应的 SQL 语句;
  2. 代码与数据库的契约:不管是从代码生成数据库(Code First),还是从数据库生成代码(Database First),核心都是基于这个模型来对齐代码和数据库的结构。

DbContext 配置和初始化

配置

配置的核心目标是让 EF Core 知道:要连接的数据库地址 / 认证信息(连接字符串)、数据库类型(SQL Server/MySQL/PostgreSQL 等)。有两种常用配置方式,适配不同场景:

OnConfiguring 方法

这是最基础的配置方式,直接在自定义 DbContext 中重写 OnConfiguring 方法,手动指定连接字符串和数据库提供器。

using Microsoft.EntityFrameworkCore;// 自定义 DbContext
public class AppDbContext : DbContext
{// 定义 DbSet(对应数据库表)public DbSet<User> Users { get; set; }// 核心配置:重写 OnConfiguring 指定数据库连接protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){// 1. 连接字符串,包含数据库地址/认证信息string sqlServerConn = "Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;";// PostgreSQL 连接字符串示例(需安装 Npgsql.EntityFrameworkCore.PostgreSQL 包)// string pgsqlConn = @"Host=myserver;Username=mylogin;Password=mypass;Database=mydatabase";// 2. 指定数据库提供器(告诉 EF Core 用哪种数据库)optionsBuilder.UseSqlServer(sqlServerConn); // SQL Server// optionsBuilder.UseNpgsql(mySqlConn, ServerVersion.AutoDetect(pgsqlConn)); // PostgreSQL}
}// 简单实体类
public class User
{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }
}
  • DbContextOptionsBuilder:EF Core 的配置构建器,专门用来设置数据库相关选项;
  • 数据库提供器需安装对应 NuGet 包(如 SQL Server 安装 Microsoft.EntityFrameworkCore.SqlServer);
  • 链接不同的数据库,需要使用 DbContextOptionsBuilder 不同的 ues* 方法,比如使用 SQLite 使用 UseSqlite、MySql 使用 UseMySql

依赖注入(DI)方法

将 DbContext 注册到依赖注入容器,由容器统一管理配置和生命周期,避免硬编码和手动管理资源。

  1. 自定义 DbContext(无需重写 OnConfiguring
using Microsoft.EntityFrameworkCore;public class AppDbContext : DbContext
{// 构造函数接收 DI 容器传入的配置(核心)public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }// 定义DbSetpublic DbSet<User> Users { get; set; }
}
  1. Program.cs 中注册 DbContext(项目入口)
using Microsoft.EntityFrameworkCore;var builder = WebApplication.CreateBuilder(args);// 1. 设置数据库连接字符串
string connStr = "Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;";// 2. 注册 DbContext 到 DI 容器
builder.Services.AddDbContext<AppDbContext>(options =>
{options.UseSqlServer(connStr); // 指定数据库提供器
});var app = builder.Build();
app.Run();
  • AddDbContext:将 DbContext 注册到 DI 容器,容器自动管理其创建 / 释放;
  • 构造函数注入 DbContextOptions<AppDbContext>:接收容器的配置,无需手动写 OnConfiguring

初始化

配置完成后,需创建 DbContext 实例才能操作数据库,对应两种配置方式有两种初始化方式:

直接 new 实例(对应 OnConfiguring 配置)

手动创建实例,必须用 using 包裹,确保使用后释放数据库连接(避免连接泄露)。

// using语句:自动释放 DbContext 资源(数据库连接)
using (var dbContext = new AppDbContext())
{// 新增数据var newUser = new User { Name = "张三", Age = 25 };dbContext.Users.Add(newUser);dbContext.SaveChanges(); // 提交更改// 查询数据var allUsers = dbContext.Users.ToList();Console.WriteLine($"共查询到 {allUsers.Count} 个用户");
}

DI 注入实例(对应 DI 配置)

在控制器、服务类中通过构造函数接收 DbContext 实例,由 DI 容器自动创建和注入,无需手动管理生命周期。

// ASP.NET Core 控制器示例
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{// 私有字段存储 DbContext 实例private readonly AppDbContext _dbContext;// 构造函数注入:DI 容器自动传入 AppDbContextpublic UserController(AppDbContext dbContext){_dbContext = dbContext;}// 接口中使用 DbContext[HttpGet]public IActionResult GetAllUsers(){var users = _dbContext.Users.ToList();return Ok(users);}
}

模型创建

模型的核心是实体类(Entity),但不是随便写的类都能被 EF Core 识别 ——EF Core 遵循 “约定优于配置” 原则,只要实体类满足基础规则,DbContext 就能自动识别;若需自定义规则,也可通过注解 / Fluent API 补充配置。

基础实体类定义(零配置)

只需遵循 EF Core 的默认约定,就能让 DbContext 自动识别实体并映射为表:

  • 主键约定:属性名为 Id 或 “实体名 + Id”(如 UserId),EF Core 自动识别为主键;int/long 类型主键默认自增。
  • 字段映射:C# 基础类型(string/int/decimal 等)自动映射为数据库对应类型。
  • 关系约定:通过 “导航属性”(如 User 中的 List<Order>)自动识别实体间的一对多 / 多对一关系。
// 示例1:用户实体(默认映射到 Users 表)
public class User
{// 主键:EF Core 自动识别 Id 为主键,int 类型默认自增public int Id { get; set; }// 普通字段:string → 数据库 nvarchar(MAX)(默认, SQL Server 的类型)public string UserName { get; set; }// 普通字段:int→数据库intpublic int Age { get; set; }// 导航属性:一对多关系,指向 Order(不生成实际列,仅用于识别关系)public List<Order> Orders { get; set; } = new List<Order>(); // 初始化避免空引用
}// 示例2:订单实体(默认映射到Orders表)
public class Order
{public int Id { get; set; }public string OrderTitle { get; set; }public decimal Amount { get; set; }// 外键约定:“关联实体名+Id”(UserId)自动识别为外键,关联 User 的 Idpublic int UserId { get; set; }// 反向导航属性:确认订单归属的用户public User User { get; set; }
}

可选:自定义模型配置

若默认规则不满足需求(如自定义表名、字段长度、主键不自增),可通过两种方式配置:

  • 数据注解(Attribute):直接标注在实体 / 属性上,简单直观;
  • Fluent API:在 DbContext 的 OnModelCreating 中配置,功能更强大,推荐复杂场景。
// 数据注解示例:自定义User实体规则
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;[Table("Sys_User")] // 自定义表名(不再默认是Users)
public class User
{[Key] // 显式标记主键(可选,默认Id已识别)[DatabaseGenerated(DatabaseGeneratedOption.None)] // 主键不自增public int Id { get; set; }[Column("UserName", TypeName = "nvarchar(50)")] // 自定义列名+长度[Required] // 非空约束public string UserName { get; set; }[Range(0, 120)] // 数值范围约束public int Age { get; set; }public List<Order> Orders { get; set; } = new List<Order>();
}

DbContext 如何自动识别模型

DbContext 是识别模型的核心,它通过 “显性声明 + 隐性发现” 的方式,把分散的实体类整合为完整的 “模型元数据”(EF Core 认知数据库结构的依据),过程分 3 步:

第一步:显性声明:通过 DbSet<T> “注册” 实体

在自定义 DbContext 中声明的 DbSet<T> 属性,是 DbContext 识别模型的核心入口,相当于明确告诉 DbContext:“这些实体需要映射到数据库表”。

using Microsoft.EntityFrameworkCore;public class AppDbContext : DbContext
{// 显性声明:告诉 DbContext 要处理 User 和 Order 实体public DbSet<User> Users { get; set; }public DbSet<Order> Orders { get; set; }// 配置数据库连接protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){string connStr = "Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;";optionsBuilder.UseSqlServer(connStr);}// 第二步:Fluent API 补充配置(可选,覆盖/补充默认规则)protected override void OnModelCreating(ModelBuilder modelBuilder){// 自定义Order的OrderTitle字段:长度100+非空modelBuilder.Entity<Order>().Property(o => o.OrderTitle).HasMaxLength(100).IsRequired();// 显式配置一对多关系(可选,默认已识别)modelBuilder.Entity<Order>().HasOne(o => o.User) // 一个订单属于一个用户.WithMany(u => u.Orders) // 一个用户有多个订单.HasForeignKey(o => o.UserId); // 外键是UserId}
}

第二步:隐性发现:通过导航属性识别关联实体

即使没在 DbContext 中声明某个实体的 DbSet<T>,只要它被已声明的实体通过导航属性引用,DbContext 也会自动发现并纳入模型。

比如:若删除 public DbSet<Order> Orders { get; set; },但 User 中有 List<Order> OrdersDbContext 依然会识别 Order 实体(因为它是 User 的关联实体)。

第三步:整合模型:OnModelCreating 最终确认

DbContext 会先基于 “默认约定 + 数据注解” 收集模型信息,再执行 OnModelCreating 方法,用 Fluent API 的配置补充 / 覆盖原有规则,最终形成完整的模型元数据—— 这是后续转换为数据库表的核心依据。

将模型转换为数据库表

DbContext 识别出完整模型后,不会直接创建表,需通过 “迁移(Migration)” 功能将模型元数据转换为数据库的 DDL(建表 SQL),核心转换规则如下:

核心转换规则(默认约定)

模型元素 数据库表 / 字段转换规则
实体类名(如 User) 表名默认是实体名的复数形式(User→Users),可通过 [Table]/Fluent API 自定义
实体属性(如 UserName) 列名默认和属性名一致,类型自动映射(stringnvarchar (MAX)intintdecimaldecimal (18,2)
主键(Id) 自动设为主键约束,int/long 类型默认自增(SQL Server:IDENTITY (1,1)
外键(UserId) 自动创建外键约束,关联主实体主键,默认开启级联删除(删除 User 时自动删除其 Orders)
导航属性(Orders) 不生成列,仅用于 EF Core 识别关系,驱动外键约束的创建

通过迁移生成实际表

执行以下命令,EF Core 会根据模型元数据生成建表 SQL 并执行:

# 1. 创建迁移文件:生成建表 SQL 脚本(存于项目 Migrations 文件夹)
Add-Migration InitialCreate# 2. 应用迁移:执行 SQL,在数据库中创建表
Update-Database

以下是 UserOrder 的表:

-- 1. 创建Users表(对应User实体)
CREATE TABLE [Users] ([Id] INT NOT NULL IDENTITY(1,1), -- 对应User.Id:主键+自增(EF Core int主键默认IDENTITY)[UserName] NVARCHAR(MAX) NULL,    -- 对应User.UserName:string默认映射nvarchar(MAX),可空[Age] INT NOT NULL,               -- 对应User.Age:int默认映射int,非空(EF Core值类型默认非空)CONSTRAINT [PK_Users] PRIMARY KEY ([Id]) -- 主键约束:对应User.Id为主键
);-- 2. 创建Orders表(对应Order实体)
CREATE TABLE [Orders] ([Id] INT NOT NULL IDENTITY(1,1),          -- 对应Order.Id:主键+自增[OrderTitle] NVARCHAR(MAX) NULL,         -- 对应Order.OrderTitle:string→nvarchar(MAX),可空[Amount] DECIMAL(18, 2) NOT NULL,        -- 对应Order.Amount:decimal默认映射decimal(18,2),非空[UserId] INT NOT NULL,                   -- 对应Order.UserId:外键字段,关联Users.IdCONSTRAINT [PK_Orders] PRIMARY KEY ([Id]), -- 主键约束-- 外键约束:对应导航属性的一对多关系(Order.User + User.Orders)CONSTRAINT [FK_Orders_Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [Users] ([Id]) ON DELETE CASCADE -- 级联删除:删除User时自动删除其关联的Order(EF Core默认行为)
);

CRUD 操作

  • 新增:用 Add/AddRange 标记新增,SaveChanges() 提交,支持级联新增;
  • 查询:核心是 LINQ 语法 +Include 加载关联数据,分页用 Skip/Take,排序用 OrderBy
  • 更新:可 “查询后修改”(自动跟踪状态)或 “无跟踪更新”(高性能),无需手动调用 Update
  • 删除:用 Remove/RemoveRange 标记删除,注意级联删除的风险,务必先查询再删除(避免误删)。

Create(新增)

通过 Add/AddRange 标记实体为 “新增状态”,调用 SaveChanges() 提交到数据库(生成 INSERT SQL)。

  • 新增单个实体
using (var dbContext = new AppDbContext())
{// 1. 创建实体对象var newUser = new User{UserName = "张三",Age = 28};// 2. 标记为新增状态(DbSet<T>.Add)dbContext.Users.Add(newUser);// 3. 提交更改(EF Core 生成 INSERT SQL 并执行)int affectedRows = dbContext.SaveChanges(); // 返回受影响的行数(此处为 1)Console.WriteLine($"新增用户成功,用户ID:{newUser.Id}"); // 新增后自动填充主键 Id
}
  • 新增关联实体:通过导航属性同时新增用户和其订单(EF Core 自动处理外键赋值)
using (var dbContext = new AppDbContext())
{var newUser = new User{UserName = "李四",Age = 30,// 导航属性赋值:关联订单Orders = new List<Order>{new Order { OrderTitle = "购买手机", Amount = 2999.99m },new Order { OrderTitle = "购买耳机", Amount = 199.99m }}};dbContext.Users.Add(newUser);dbContext.SaveChanges();Console.WriteLine($"新增用户ID:{newUser.Id},关联订单数:{newUser.Orders.Count}");// 订单的UserId会自动填充为 newUser.Id,无需手动赋值
}
  • 批量增加
using (var dbContext = new AppDbContext())
{var userList = new List<User>{new User { UserName = "王五", Age = 25 },new User { UserName = "赵六", Age = 35 }};// AddRange:批量标记新增dbContext.Users.AddRange(userList);dbContext.SaveChanges();Console.WriteLine($"批量新增 {userList.Count} 个用户完成");
}

Read(查询)

查询是 CRUD 中最灵活的操作,核心是通过 LINQ 语法描述查询条件,EF Core 自动转换为 SELECT SQL。

  • 基础查询
using (var dbContext = new AppDbContext())
{// 1. 查询所有用户(生成:SELECT * FROM Users)var allUsers = dbContext.Users.ToList();// 2. 查询单个用户(按主键,找不到返回 null,推荐用 FirstOrDefault)var targetUser = dbContext.Users.FirstOrDefault(u => u.Id == 1);// 注意:SingleOrDefault要求结果只能是0或1条,多了会报错;FirstOrDefault取第一条,更安全// 3. 条件查询(年龄>25的用户,生成:SELECT * FROM Users WHERE Age > 25)var adultUsers = dbContext.Users.Where(u => u.Age > 25).ToList();// 4. 只查询指定字段(避免SELECT *,提升性能)var userNames = dbContext.Users.Select(u => new { u.Id, u.UserName }).ToList();
}
  • 关联数据查询:默认情况下 EF Core 不会加载导航属性(如 User.Orders),需用 Include 显式加载。
using (var dbContext = new AppDbContext())
{// 1. 加载用户+关联的所有订单(生成 JOIN SQL)var userWithOrders = dbContext.Users.Include(u => u.Orders) // 关键:加载导航属性 Orders.FirstOrDefault(u => u.Id == 1);if (userWithOrders != null){Console.WriteLine($"用户{userWithOrders.UserName}有{userWithOrders.Orders.Count}个订单");}// 2. 加载订单+关联的用户(反向导航)var orderWithUser = dbContext.Orders.Include(o => o.User).FirstOrDefault(o => o.Id == 1);Console.WriteLine($"订单{orderWithUser.Id}所属用户:{orderWithUser.User.UserName}");
}
  • 分页 + 排序查询
using (var dbContext = new AppDbContext())
{int pageIndex = 1; // 页码(从 1 开始)int pageSize = 10; // 每页条数var pagedUsers = dbContext.Users.OrderByDescending(u => u.Age) // 按年龄降序排序.Skip((pageIndex - 1) * pageSize) // 跳过前面的记录.Take(pageSize) // 取指定条数.ToList();// 总条数(用于计算总页数)int totalCount = dbContext.Users.Count();Console.WriteLine($"第{pageIndex}页,共{totalCount}条数据");
}

Update(更新)

EF Core 跟踪实体状态,修改实体属性后调用 SaveChanges(),自动生成 UPDATE SQL。

  • 基础更新(查询→修改→提交)
using (var dbContext = new AppDbContext())
{// 1. 先查询要更新的实体(EF Core 开始跟踪该实体)var userToUpdate = dbContext.Users.FirstOrDefault(u => u.Id == 1);if (userToUpdate == null) return;// 2. 修改属性(EF Core自动标记为“修改状态”)userToUpdate.Age = 29;userToUpdate.UserName = "张三_修改后";// 3. 提交更改(无需手动调用 Update,EF Core 已跟踪状态)dbContext.SaveChanges();Console.WriteLine("用户信息更新完成");
}
  • 无跟踪更新:如果已知实体主键,可通过 Attach 手动标记状态,避免额外的查询操作。
using (var dbContext = new AppDbContext())
{// 1. 创建仅含主键和要修改字段的实体var userToUpdate = new User { Id = 1, Age = 30 };// 2. 附加到 DbContext 并标记为“修改状态”dbContext.Users.Attach(userToUpdate);dbContext.Entry(userToUpdate).Property(u => u.Age).IsModified = true; // 仅标记 Age 为修改// 3. 提交更改dbContext.SaveChanges();
}
  • 批量更新
using (var dbContext = new AppDbContext())
{// 1. 查询要批量更新的实体var usersToUpdate = dbContext.Users.Where(u => u.Age < 30).ToList();// 2. 批量修改foreach (var user in usersToUpdate){user.Age += 1; // 年龄+1}// 3. 提交dbContext.SaveChanges();
}

Delete(删除)

通过 Remove/RemoveRange 标记实体为 “删除状态”,调用 SaveChanges() 生成 DELETE SQL。

  • 单个实体删除
using (var dbContext = new AppDbContext())
{// 1. 查询要删除的实体var userToDelete = dbContext.Users.FirstOrDefault(u => u.Id == 2);if (userToDelete == null) return;// 2. 标记为删除状态dbContext.Users.Remove(userToDelete);// 3. 提交更改dbContext.SaveChanges();Console.WriteLine("用户删除完成");
}
  • 关联实体删除
using (var dbContext = new AppDbContext())
{var userToDelete = dbContext.Users.Include(u => u.Orders).FirstOrDefault(u => u.Id == 1);if (userToDelete == null) return;// 删除用户 → 级联删除其所有订单dbContext.Users.Remove(userToDelete);dbContext.SaveChanges();Console.WriteLine($"删除用户{userToDelete.Id},同时删除{userToDelete.Orders.Count}个订单");
}
  • 批量删除
using (var dbContext = new AppDbContext())
{// 1. 查询要批量删除的实体var ordersToDelete = dbContext.Orders.Where(o => o.Amount < 200).ToList();// 2. 批量标记删除dbContext.Orders.RemoveRange(ordersToDelete);// 3. 提交dbContext.SaveChanges();Console.WriteLine($"批量删除{ordersToDelete.Count}个订单");
}

额外内容

在内存中的数据库

EF Core 提供的 InMemory 数据库是一个轻量级的内存数据库模拟器,它不依赖任何真实数据库引擎,数据仅存储在应用内存中,程序重启后数据全部丢失。

适合于单元测试、快速验证模型 / CRUD 逻辑、原型开发。

  1. 使用前需先安装 InMemory
dotnet add package Microsoft.EntityFrameworkCore.InMemory
  1. 配置 DbContext 使用内存数据库
// OnConfiguring 方法
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){// 关键:使用内存数据库,指定数据库名称(标识唯一的内存数据库实例)optionsBuilder.UseInMemoryDatabase("MyDatabase");}
// 依赖注入配置方法
var services = new ServiceCollection();
services.AddDbContext<AppDbContext>(options =>
{// 配置内存数据库,每次创建新实例(避免测试用例互相干扰)options.UseInMemoryDatabase("MyDatabase");
});

异步编程

数据库操作(查询 / 新增 / 更新 / 删除)属于 IO 密集型操作,同步编程会让线程等待数据库响应(期间线程闲置);而异步编程能让线程在等待时去处理其他请求,大幅提升应用的并发处理能力。

EF Core 提供了一套和同步 API 对应的异步方法(后缀为 Async),语法和同步操作几乎一致,只需配合 async/await 关键字使用。

异步 CRUD 语法和同步几乎一致,仅需将同步方法替换为异步版本并添加 await

简单且完整的案例

在开始之前,需要安装如下两个 Nuget 包:

dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.InMemory
  • 实体类:User.cs
namespace ConsoleApp1;public class User
{public int Id { get; set; }public string? Name { get; set; }public int Age { get; set; }
}
  • 数据库上下文管理器:AppDbContext.cs
using Microsoft.EntityFrameworkCore;namespace ConsoleApp1;public class AppDbContext : DbContext
{public DbSet<User> Users { get; set;}protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){optionsBuilder.UseInMemoryDatabase("MyDatabase");}
}
  • 启动类:Program.cs
using ConsoleApp1;using (var dbContext = new AppDbContext())
{// 新增var newUser = new User { Name = "张三", Age = 25 };dbContext.Users.Add(newUser);dbContext.SaveChanges();Console.WriteLine($"新增用户: {newUser.Name}, 年龄: {newUser.Age}, ID: {newUser.Id}");// 查询var users = dbContext.Users.ToList();Console.WriteLine("查询所有用户:");foreach (var user in users){Console.WriteLine($"ID: {user.Id}, 姓名: {user.Name}, 年龄: {user.Age}");}// 更新var userToUpdate = dbContext.Users.FirstOrDefault(u => u.Name == "张三");if (userToUpdate != null){userToUpdate.Age = 26;dbContext.SaveChanges();Console.WriteLine($"更新用户年龄为: {userToUpdate.Age}");}// 删除var userToDelete = dbContext.Users.FirstOrDefault(u => u.Name == "张三");if (userToDelete != null){dbContext.Users.Remove(userToDelete);dbContext.SaveChanges();Console.WriteLine($"删除用户: {userToDelete.Name}");}
}

参考链接

  • Entity Framework Core 概述 - EF Core | Microsoft Learn
  • DbContext 生存期、配置和初始化 - EF Core | Microsoft Learn
  • 创建和配置模型 - EF Core | Microsoft Learn
  • 异步编程 - EF Core | Microsoft Learn
  • 数据库提供程序 - EF Core | Microsoft Learn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1195637.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

std::function

std::function 类模板 std::function 是一个通用的多态函数封装器。std::function 实例可以存储、复制和调用任何可复制构造的(CopyConstructible)可调用对象(Callable) 目标——函数(通过其指针)、lambda 表达式…

std::thread创建线程访问类成员

方法一&#xff1a;std::bind 成员函数class TaskHelp { public:TaskHelp() default;~TaskHelp(){StopTask();}public:// 线程函数void ThreadFunc(){// todo 其他事项// 访问类成员std::cout << m_status.c_str() <<std::endl;}// 方法一void StartTask_v1(){m_…

2026年苏州GEO优化公司推荐:专业服务商选型指南

随着生成式AI技术的快速发展,GEO(生成式引擎优化)已成为企业在AI搜索场景中获取品牌曝光的关键策略。对于苏州本地企业而言,选择专业的GEO优化服务商,能够有效提升品牌在AI问答中的可见度与引用率。本文将从技术能力、…

unet image Face Fusion容器化打包?Dockerfile编写最佳实践

unet image Face Fusion容器化打包&#xff1f;Dockerfile编写最佳实践 1. 背景与目标&#xff1a;为什么要做容器化打包 你有没有遇到过这种情况&#xff1a;在本地调试得好好的人脸融合项目&#xff0c;换一台机器就各种报错&#xff1f;依赖版本冲突、环境变量缺失、Pytho…

瑞祥商联卡回收的三种省心途径(2026年)

瑞祥商联卡回收的三种省心途径(2026年)瑞祥商联卡在江浙沪地区流通极广,社区便利店、大型商超、餐饮门店等多场景均可使用,既是企业节日福利的热门选择,也是日常消费的实用工具。不少人手中会囤积闲置卡片,或因工…

堡垒机底层协议开发

堡垒机&#xff08;Jump Server 或 Bastion Host&#xff09;的底层协议开发涉及多个网络协议、安全机制和系统集成技术。如果你正在从事或计划进行堡垒机底层协议的开发&#xff0c;以下是一些关键的技术要点和建议&#xff1a; 一、核心目标 堡垒机的核心功能是&#xff1a;…

2026年呼叫中心公司推荐:厂商详细盘点与解析指南

在数字化转型深化的背景下,呼叫中心已从传统语音渠道升级为“营、销、服”全场景智能联络枢纽,云原生、AI大模型融合、全渠道整合成为核心趋势。企业选型时,不仅关注稳定性与功能适配,更看重技术合规性、智能化效率…

江苏柴油发电机公司如何选择?这五家实力企业值得关注

转载自:https://www.pp10top.com/rankinglis/293712.html 文章摘要 随着工业发展、数据中心扩张及应急供电需求增长,江苏地区柴油发电机市场持续活跃。本文基于行业趋势,从技术实力、产品可靠性、服务网络及市场口碑…

.NET微服务架构:从开发到部署全指南

你列出的这些技术栈&#xff08;.NET Core、RabbitMQ、EF Core、Web API、TCP、Swagger、Linux、Docker&#xff09;构成了一个典型的现代化微服务或分布式系统开发环境。下面我为你简要梳理它们各自的角色&#xff0c;并提供一些整合建议和最佳实践&#xff1a;1. .NET Core&a…

2026年1月中国健身器材行业竞争格局深度分析报告

一、核心结论 1.1 核心评估框架 本次评估基于行业核心竞争力维度,选取四大关键指标构建评估体系,确保分析客观性与全面性:技术研发实力:聚焦智能硬件集成、核心零部件自研能力及专利布局密度,衡量企业产品迭代护城…

一文看懂 Android 热点如何“智能”开启 5GHz 频段:从代码到用户体验的完整解析

你有没有注意到&#xff0c;有些安卓手机在开启 Wi-Fi 热点&#xff08;即“网络共享”&#xff09;时&#xff0c;可以自动使用 5GHz 频段&#xff0c;而有些却只能用 2.4GHz&#xff1f; 更神奇的是&#xff0c;明明硬件支持 5GHz&#xff0c;但热点选项里却看不到“5GHz”这…

Unsloth模型合并:LoRA权重整合详细步骤

Unsloth模型合并&#xff1a;LoRA权重整合详细步骤 1. unsloth 简介 你是否在为大语言模型&#xff08;LLM&#xff09;微调时显存占用高、训练速度慢而烦恼&#xff1f;Unsloth 正是为此而生。它是一个开源的 LLM 微调和强化学习框架&#xff0c;专注于提升训练效率与资源利…

2026疲劳试验机选对厂家很重要:品质好、型号全的企业推荐

随着中国制造业向高端化、智能化纵深发展,对材料与核心零部件的性能评估要求达到了前所未有的高度。作为保障装备安全性与可靠性的“工业裁判”,疲劳试验机行业正迎来战略机遇期。在航空航天、新能源汽车、轨道交通、…

2026西安口碑好的宝宝起名公司高端专业起名机构精选

对西安准父母和新生儿家庭来说,给宝宝起一个合适的名字,是开启育儿之路的重要仪式。既要兼顾音律美感与文化底蕴,规避重名、谐音陷阱,又要寄托对孩子未来的期许,这份纠结让不少家长倍感焦虑。市面上起名服务良莠不…

Mandiant发布快速凭据破解工具,加速淘汰微软老旧协议

谷歌安全部门Mandiant上周发布了能够在12小时内破解凭据的工具&#xff0c;希望借此加速淘汰微软一个古老的安全协议的使用。 据Mandiant发布的文章解释&#xff0c;20多年来研究人员一直知道微软的Net-NTLMv1传统身份验证协议会使用户面临凭据盗窃风险&#xff0c;但该协议至今…

rust并发安全特性

在 Rust 中,并发安全(Fearless Concurrency)并非事后补丁,而是植根于其核心设计之中的。它主要通过所有权系统、类型系统标记以及标准库原语在编译阶段消除数据竞争。 以下是Rust 并发安全的四大核心特征: 1. 核心…

2026柔板印刷机选购:哪些公司口碑佳?比较好的柔板印刷机推荐榜10年质保有保障

在包装印刷、标签生产等工业领域,柔板印刷机凭借其环保、高效、适应多材质的特性,已成为保障产品质量、提升生产效率的核心设备。尤其在食品包装、医药标签等对安全性要求极高的场景中,新型柔板印刷机的稳定性与技术…

国产PCB设计软件推荐:这款高效工具,助你轻松完成国产替代

在当前全球半导体产业链加速重构的背景下,国产PCB软件、自主可控的EDA工具已成为电子研发团队的重要关注点。随着国产化需求上升,越来越多企业开始评估替代方案,以应对供应链安全与数据合规挑战。国产PCB软件不仅关…

Oracle向KingbaseES迁移:核心痛点拆解与根源分析

目录引一、从核心问题词看迁移的显性痛点二、兼容性挑战&#xff1a;迁移的深层隐性痛点1. 语法与参数兼容痛点2. 数据类型与格式兼容痛点3. 接口与驱动兼容痛点4. 功能特性兼容痛点三、迁移成本&#xff1a;可控性差的全流程痛点1. 人力成本居高不下2. 时间成本不可控3. 试错成…

论文笔记:[3D Gaussian Splatting for Real-Time Radiance Field Rendering]

1. 基础信息 标题: 3D Gaussian Splatting for Real-Time Radiance Field Rendering作者与机构: Inria出处与年份: SIGGRAPH 2023项目主页&#xff1a;3D Gaussian Splatting for Real-Time Radiance Field Rendering主要参考&#xff1a; 三维高斯泼溅的实践与原理 | 唐玥璨b…