EF Core 与 MySQL:介绍与入门实操
<h2>简介</h2><p>EF Core(Entity Framework Core)是Microsoft推出的开源跨平台ORM框架,支持SQL Server、SQLite、MySQL、PostgreSQL等主流数据库,并提供向NoSQL数据库(如Cosmos DB)的扩展能力。它通过DbContext管理实体与数据库的映射关系,提供LINQ查询、CRUD操作及数据库迁移功能,适用于微服务架构、Web API开发等场景。</p>
<h2>核心架构与功能</h2>
<ul>
<li><strong>DbContext</strong>:作为EF Core的核心类,管理数据库连接和实体对象映射,所有CRUD操作均通过其实现。典型用法包括继承DbContext并配置DbSet属性来映射数据库表。</li>
<li><strong>数据库支持</strong>:兼容SQL Server、MySQL、PostgreSQL、SQLite等主流数据库,通过NuGet包集成不同提供程序(如Microsoft.EntityFrameworkCore.SqlServer)。</li>
<li><strong>LINQ查询</strong>:允许开发者使用面向对象的方式编写查询,减少直接SQL编写需求。</li>
</ul>
<h2>性能优化</h2>
<ul>
<li><strong>DbContext池化</strong>:通过AddDbContextPool复用上下文实例,减少高频创建开销,适用于高性能场景。</li>
<li><strong>异步操作</strong>:支持异步方法如SaveChangesAsync,提升应用响应能力。</li>
</ul>
<h2>开发流程</h2>
<ul>
<li><strong>模型定义</strong>:通过实体类映射数据库表结构,例如Blog和Post类的一对多关系。</li>
<li><strong>迁移与架构管理</strong>:使用命令行工具生成迁移脚本,同步数据库结构变更。</li>
<li><strong>依赖注入集成</strong>:在ASP.NET Core中通过AddDbContext注册服务,实现控制器自动注入。</li>
</ul>
<h2>版本与兼容性</h2>
<ul>
<li>当前稳定版本为EF Core 9.0(支持至2026年5月),目标框架为.NET 8,提供跨平台兼容性(Windows/Linux/macOS)。历史版本如EF Core 5.0基于.NET Standard 2.1,已停止支持。</li>
</ul>
<h2>应用场景</h2>
<ul>
<li><strong>微服务架构</strong>:管理各服务的私有数据库。</li>
<li><strong>Web API开发</strong>:与ASP.NET Core深度集成,快速构建数据驱动接口。</li>
</ul>
<h2>入门实操</h2>
<p>在本文中,将使用 Entity Framework Core 8.0 对 MySQL 5.7.2 数据库执行数据访问。</p>
<h3>1、安装依赖</h3>
<p style="margin-left: 30px">确保已安装.NET SDK(推荐8.0)和MySQL数据库。通过NuGet包管理器或者以下命令添加NuGet包:</p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre>--<span style="color: rgba(0, 0, 0, 1)">包
Microsoft.EntityFrameworkCore
Pomelo.EntityFrameworkCore.MySql
Microsoft.EntityFrameworkCore.Tools
</span>--<span style="color: rgba(0, 0, 0, 1)">命令
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Pomelo.EntityFrameworkCore.MySql
dotnet add package Microsoft.EntityFrameworkCore.Tools</span></pre>
</div>
<p style="margin-left: 30px"><strong>注意:版本的选择尽量与.NET版本一致,我这里使用的.NET8.0。</strong></p>
<h3>2、连接字符串配置</h3>
<p style="margin-left: 30px">在appsettings.json中配置MySQL连接信息:</p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre>{ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ConnectionStrings</span><span style="color: rgba(128, 0, 0, 1)">"</span>: { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DefaultConnection</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">server=localhost;port=3306;database=testdb;user=root;password=yourpassword;</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> } }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">或直接在DbContext中配置:</span><span style="color: rgba(0, 0, 0, 1)">
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));</span></pre>
</div>
<p style="margin-left: 30px"><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914171325908-1017674269.png"></p>
<h3>3、创建实体模型</h3>
<p style="margin-left: 30px">定义与数据库表对应的实体类,例如:</p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> CP.ProductService.Domains.Models
{
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 商品 聚合根
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Product
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> Id { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">decimal</span> Price { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Description { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> List<ProductImage> ProductImages { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}
}</span></pre>
</div>
<div class="cnblogs_code" style="margin-left: 30px">
<pre><span style="color: rgba(0, 0, 0, 1)">namespace CP.ProductService.Domains.Models
{
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 商品图片 【实体】
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 0, 0, 1)"> public class ProductImage
{
public </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> Id { get; set; }
public </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Name { get; set; }
public </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Path { get; set; }
public </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Description { get; set; }
}
}</span></pre>
</div>
<h3>4、配置DbContext上下文</h3>
<p style="margin-left: 30px">创建上下文类并映射实体集:</p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> CP.ProductService.Domains.Models;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.EntityFrameworkCore;
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> CP.ProductService.Infrastructures.Datas
{
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 创建上下文
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ProductContext : DbContext
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> ProductContext(DbContextOptions options) : <span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">(options)
{
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">=> optionsBuilder.UseMySql("Serve=localhost;Port=3306;DataBase=ProductService;Uid=root;Pwd=123456;"
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> , new MySqlServerVersion("5.7.29"));</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> DbSet<Product> Products { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}
}<br></span></pre>
</div>
<h3>5、依赖注入</h3>
<p style="margin-left: 30px">在program.cs中注入UserContext依赖:</p>
<div class="cnblogs_code" style="margin-left: 30px">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1、注册ProductContext</span>
builder.Services.AddDbContext<ProductContext>(option =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2、使用MySql</span>
option.UseMySql(builder.Configuration.GetConnectionString(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Default</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">),
</span><span style="color: rgba(0, 0, 255, 1)">new</span> MySqlServerVersion(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5.7.29</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">));
});</span></pre>
</div>
<h3>6、使用迁移来创建数据库</h3>
<ul>
<li style="list-style-type: none">
<ul>
<li><strong>验证是否已正确安装 EF Core CLI 工具:<br></strong>dotnet ef 是 Entity Framework Core 提供的命令行工具,用于执行数据库迁移、模型代码生成等设计时任务。<br>
<div class="cnblogs_code">
<pre>dotnet ef</pre>
</div>
</li>
</ul>
</li>
</ul>
<p style="margin-left: 60px"><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914183818644-884411174.png"></p>
<p style="margin-left: 60px">如上图所示,看到这个符号就是已安装成功。</p>
<p style="margin-left: 60px">注意:如果工具未安装就运行”dotnet ef“,会报”<em>无法执行,因为找不到指定的命令或文件。可能造成此问题的原因包括:*内置 dotnet 命令拼写错误。*你打算执行 .NET 程序,但 dotnet-ef 不存在。*你打算运行全局工具,但在 PATH 上找不到具有此名称且带有 dotnet 前缀的可执行文件。“的错误,如下图。</em></p>
<p style="margin-left: 60px"><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914235445700-1498834901.png"></p>
<ul>
<li style="list-style-type: none">
<ul>
<li><strong>安装工具dotnet ef <br></strong>上一步验证未安装成功的按以下命令安装,验证安装成功的可以忽略这一步。</li>
</ul>
</li>
</ul>
<div class="cnblogs_code" style="margin-left: 60px">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">安装最新版</span>
dotnet tool <span style="color: rgba(0, 0, 255, 1)">install</span> --global dotnet-<span style="color: rgba(0, 0, 0, 1)">ef
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">安装指定版本(避免兼容性问题)</span>
dotnet tool <span style="color: rgba(0, 0, 255, 1)">install</span> --global dotnet-ef --version <span style="color: rgba(128, 0, 128, 1)">8.0</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">顺便记录下卸载命令</span>
dotnet tool uninstall --global dotnet-ef</pre>
</div>
<p style="margin-left: 60px"><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914183423238-1490408970.png"></p>
<ul>
<li style="list-style-type: none">
<ul>
<li class="marklang-paragraph"><strong>初始化迁移</strong>(使用的是 Code First 迁移)</li>
</ul>
</li>
</ul>
<p class="marklang-paragraph" style="margin-left: 60px">migrations 命令为迁移搭建基架,为模型创建初始表集。</p>
<div class="cnblogs_code" style="margin-left: 60px">
<pre>dotnet ef migrations add InitialCreate</pre>
</div>
<p style="margin-left: 60px"><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914190937073-5631402.png"></p>
<p style="margin-left: 60px"><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914191123858-1082083368.png"></p>
<p style="margin-left: 60px"> 可以看到迁移类文件已生成。</p>
<ul>
<li style="list-style-type: none">
<ul>
<li class="marklang-paragraph"><strong>更新数据库架构</strong></li>
</ul>
</li>
</ul>
<p class="marklang-paragraph" style="margin-left: 60px">database update 命令将创建数据库,并将新的迁移应用到该数据库。</p>
<div class="cnblogs_code" style="margin-left: 60px">
<pre>dotnet ef database update</pre>
</div>
<p style="margin-left: 60px"><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914191839064-1529191862.png"></p>
<p style="margin-left: 60px"><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914191953670-1118586282.png"></p>
<p style="margin-left: 60px"> 可以看到数据库和表都生成了。</p>
<ul>
<li style="list-style-type: none">
<ul>
<li class="marklang-paragraph"><strong>更新迁移和数据库架构</strong><br>数据库和表结构有变化时,需要更新迁移,更新时必须新定义一个迁移类名,如下依次执行命令。<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">dotnet ef migrations add InitialCreate_xxx
dotnet ef database update</span></pre>
</div>
<p>改一下ProductImage实体类的字段,Path改为Url,依次执行以上两个命令,会生成增量迁移类文件,数据库里ProductImage表字段也会更新,效果如下图。</p>
<p><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250915001420066-1554901686.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250915001922895-976283489.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250915002754970-2055708454.png"></p>
<p>注意:如果迁移类名用已存在的迁移类名,会报”<em>The name 'xxxxx' is used by an existing migration.</em>“的错误,如下图。</p>
<p><img src="https://img2024.cnblogs.com/blog/600074/202509/600074-20250914234727992-1769851937.png"> </p>
</li>
</ul>
</li>
</ul>
<h3>7、基本增删查改操作</h3>
<ul>
<li style="list-style-type: none">
<ul>
<li class="marklang-paragraph"><strong><strong>直接上示例代码</strong></strong>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 添加数据</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> context = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ProductContext())
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> product = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Product{
Name </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Laptop</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
Price </span>= <span style="color: rgba(128, 0, 128, 1)">999.99m</span><span style="color: rgba(0, 0, 0, 1)">,
Description</span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">笔记本</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
};
context.Products.Add(product);
context.SaveChanges();
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 查询数据</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> context = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ProductContext())
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> expensiveProducts =<span style="color: rgba(0, 0, 0, 1)"> context.Products
.Where(p </span>=> p.Price > <span style="color: rgba(128, 0, 128, 1)">500</span><span style="color: rgba(0, 0, 0, 1)">)
.OrderByDescending(p </span>=><span style="color: rgba(0, 0, 0, 1)"> p.Price)
.ToList();
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 更新数据</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> context = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ProductContext())
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> product = context.Products.FirstOrDefault(p => p.Name == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Laptop</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (product != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
{
product.Price </span>= <span style="color: rgba(128, 0, 128, 1)">899.99m</span><span style="color: rgba(0, 0, 0, 1)">;
context.SaveChanges();
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 删除数据</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> context = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ProductContext())
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> product = context.Products.FirstOrDefault(p => p.Name == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Laptop</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (product != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
{
context.Products.Remove(product);
context.SaveChanges();
}
}</span></pre>
</div>
</li>
</ul>
</li>
</ul>
<h2 class="marklang-paragraph">总结</h2>
<p class="marklang-paragraph">本文主要介绍了EF Core的理论部分,如何使用EF Core连接MySQL执行数据访问,包括模型创建、DbContext配置、数据库迁移以及基本的增删改查操作。</p>
<p class="marklang-paragraph"> </p><br><br>
来源:https://www.cnblogs.com/jixingsuiyuan/p/19091441
頁:
[1]