news 2026/5/5 14:59:36

不止于连接:在WPF应用中用Entity Framework Core 7操作MySQL数据库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
不止于连接:在WPF应用中用Entity Framework Core 7操作MySQL数据库

不止于连接:在WPF应用中用Entity Framework Core 7操作MySQL数据库

当WPF开发者需要处理数据库时,很多人第一反应是直接使用MySqlConnectionMySqlCommand——这就像用螺丝刀组装家具,虽然能完成任务,但效率远不如电动工具。Entity Framework Core 7(EF Core 7)就是这样的"电动工具",它让数据操作从机械的连接/命令模式,升级到面向对象的优雅范式。

我仍然记得第一次在WPF项目中使用EF Core时的震撼:原本需要几十行代码的CRUD操作,现在几行就能完成;原本需要手动维护的SQL脚本,现在通过迁移(Migration)自动生成。更重要的是,代码的可读性和可维护性大幅提升——数据操作不再隐藏在字符串拼接的SQL中,而是变成了直观的对象方法和属性。

1. 为什么选择EF Core 7而非原生ADO.NET

在比较两种数据库操作方式前,我们先看一个典型场景:向Products表插入一条记录并查询所有单价大于100的产品。

原生ADO.NET实现

// 插入 using var conn = new MySqlConnection(connectionString); var insertCmd = new MySqlCommand( "INSERT INTO Products (Name, Price) VALUES (@name, @price)", conn); insertCmd.Parameters.AddWithValue("@name", "Premium Coffee"); insertCmd.Parameters.AddWithValue("@price", 120); conn.Open(); insertCmd.ExecuteNonQuery(); // 查询 var selectCmd = new MySqlCommand( "SELECT * FROM Products WHERE Price > @threshold", conn); selectCmd.Parameters.AddWithValue("@threshold", 100); var reader = selectCmd.ExecuteReader(); while (reader.Read()) { Console.WriteLine($"{reader["Name"]} - {reader["Price"]}"); }

EF Core 7实现

// 插入 await _dbContext.Products.AddAsync(new Product { Name = "Premium Coffee", Price = 120 }); await _dbContext.SaveChangesAsync(); // 查询 var expensiveProducts = await _dbContext.Products .Where(p => p.Price > 100) .ToListAsync();

对比之下,EF Core的优势显而易见:

  • 代码简洁性:无需手动编写SQL,避免字符串拼接错误
  • 强类型检查:编译时就能发现属性名拼写错误
  • LINQ集成:可以使用熟悉的LINQ语法进行复杂查询
  • 异步支持:原生支持async/await,避免UI线程阻塞
  • 变更追踪:自动跟踪实体状态变化,简化更新操作

提示:对于简单的查询,ADO.NET可能更快,但在大多数业务应用中,EF Core的生产力优势远大于微小的性能差异。

2. 配置WPF项目使用EF Core 7

2.1 环境准备

首先创建新的WPF项目,并通过NuGet安装必要包:

dotnet add package Microsoft.EntityFrameworkCore dotnet add package Microsoft.EntityFrameworkCore.Design dotnet add package Pomelo.EntityFrameworkCore.MySql

为什么选择Pomelo而不是官方的MySQL提供程序?因为它:

  • 支持EF Core的所有最新功能
  • 活跃的社区维护
  • 更好的性能优化

2.2 配置DbContext

创建继承自DbContext的应用程序数据库上下文:

public class AppDbContext : DbContext { public DbSet<Product> Products { get; set; } public DbSet<Customer> Customers { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) { options.UseMySql( "server=localhost;database=ShopDB;user=root;password=your_pwd", new MySqlServerVersion(new Version(8, 0, 34)), options => options.EnableRetryOnFailure()); } }

但在WPF中更好的做法是使用依赖注入:

// App.xaml.cs public partial class App : Application { public static IServiceProvider ServiceProvider { get; private set; } protected override void OnStartup(StartupEventArgs e) { var services = new ServiceCollection(); services.AddDbContext<AppDbContext>(options => options.UseMySql(Configuration.GetConnectionString("Default"), ServerVersion.AutoDetect(Configuration.GetConnectionString("Default")))); ServiceProvider = services.BuildServiceProvider(); } }

3. 数据建模与迁移

3.1 定义实体模型

采用Code First方式,我们先定义业务实体:

public class Product { public int Id { get; set; } [Required] [MaxLength(100)] public string Name { get; set; } [Column(TypeName = "decimal(18,2)")] public decimal Price { get; set; } public int CategoryId { get; set; } public Category Category { get; set; } } public class Category { public int Id { get; set; } public string Name { get; set; } public ICollection<Product> Products { get; set; } }

3.2 数据库迁移

通过包管理器控制台执行:

Add-Migration InitialCreate Update-Database

这会生成并执行如下SQL:

CREATE TABLE `Categories` ( `Id` int NOT NULL AUTO_INCREMENT, `Name` longtext CHARACTER SET utf8mb4 NULL, CONSTRAINT `PK_Categories` PRIMARY KEY (`Id`) ); CREATE TABLE `Products` ( `Id` int NOT NULL AUTO_INCREMENT, `Name` varchar(100) CHARACTER SET utf8mb4 NOT NULL, `Price` decimal(18,2) NOT NULL, `CategoryId` int NOT NULL, CONSTRAINT `PK_Products` PRIMARY KEY (`Id`), CONSTRAINT `FK_Products_Categories_CategoryId` FOREIGN KEY (`CategoryId`) REFERENCES `Categories` (`Id`) ON DELETE CASCADE );

4. 在WPF中实现CRUD操作

4.1 依赖注入DbContext

在ViewModel中注入DbContext:

public class MainViewModel { private readonly AppDbContext _dbContext; public MainViewModel(AppDbContext dbContext) { _dbContext = dbContext; LoadProducts(); } public ObservableCollection<Product> Products { get; } = new(); private async void LoadProducts() { var products = await _dbContext.Products .Include(p => p.Category) .ToListAsync(); Products.Clear(); foreach (var p in products) { Products.Add(p); } } }

4.2 增删改查实现

添加新产品

private async Task AddProductAsync(string name, decimal price) { var product = new Product { Name = name, Price = price }; _dbContext.Products.Add(product); await _dbContext.SaveChangesAsync(); LoadProducts(); // 刷新列表 }

批量更新

private async Task ApplyDiscountAsync(decimal discountRate) { var products = await _dbContext.Products .Where(p => p.Price > 100) .ToListAsync(); foreach (var p in products) { p.Price *= (1 - discountRate); } await _dbContext.SaveChangesAsync(); }

复杂查询

public async Task<List<Product>> GetTopExpensiveProductsAsync(int count) { return await _dbContext.Products .OrderByDescending(p => p.Price) .Take(count) .Include(p => p.Category) .AsNoTracking() // 只读场景提升性能 .ToListAsync(); }

5. 性能优化与高级技巧

5.1 批量操作优化

EF Core 7新增的批量操作API:

// 批量删除 await _dbContext.Products .Where(p => p.Price < 10) .ExecuteDeleteAsync(); // 批量更新 await _dbContext.Products .Where(p => p.CategoryId == 1) .ExecuteUpdateAsync(setters => setters.SetProperty(p => p.Price, p => p.Price * 1.1m));

5.2 并发控制

使用并发令牌处理并发更新:

public class Product { // ... [Timestamp] public byte[] RowVersion { get; set; } } try { await _dbContext.SaveChangesAsync(); } catch (DbUpdateConcurrencyException ex) { var entry = ex.Entries.Single(); var databaseValues = await entry.GetDatabaseValuesAsync(); // 解决策略:合并更改或提示用户 entry.OriginalValues.SetValues(databaseValues); await _dbContext.SaveChangesAsync(); }

5.3 查询性能分析

使用TagWith记录查询目的:

var results = await _dbContext.Products .TagWith("获取首页推荐商品") .Where(p => p.IsFeatured) .ToListAsync();

在MySQL日志中会看到:

/* 获取首页推荐商品 */ SELECT `p`.`Id`, `p`.`Name`, `p`.`Price` FROM `Products` AS `p` WHERE `p`.`IsFeatured` = TRUE

6. 实战:在WPF中实现主从视图

结合WPF的数据绑定特性,我们可以轻松实现主从视图:

<!-- MainWindow.xaml --> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> <ListBox ItemsSource="{Binding Categories}" SelectedItem="{Binding SelectedCategory}"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <DataGrid Grid.Column="1" ItemsSource="{Binding SelectedCategory.Products}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="名称" Binding="{Binding Name}"/> <DataGridTextColumn Header="价格" Binding="{Binding Price}"/> </DataGrid.Columns> </DataGrid> </Grid>

ViewModel只需正确加载包含关联的数据:

public ObservableCollection<Category> Categories { get; } = new(); public async Task LoadDataAsync() { var categories = await _dbContext.Categories .Include(c => c.Products) .AsNoTracking() .ToListAsync(); Categories.Clear(); foreach (var c in categories) { Categories.Add(c); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 14:49:26

3步打造专属精简Windows 11:告别系统臃肿,拥抱极致性能

3步打造专属精简Windows 11&#xff1a;告别系统臃肿&#xff0c;拥抱极致性能 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder 你是否曾经为Windows 11的臃肿感到…

作者头像 李华
网站建设 2026/5/5 14:46:49

Autovisor:智慧树网课自动化学习的终极解决方案

Autovisor&#xff1a;智慧树网课自动化学习的终极解决方案 【免费下载链接】Autovisor 2025智慧树刷课脚本 基于Python Playwright的自动化程序 [有免安装版] 项目地址: https://gitcode.com/gh_mirrors/au/Autovisor 还在为智慧树网课的手动操作而烦恼吗&#xff1f;每…

作者头像 李华
网站建设 2026/5/5 14:44:53

创业团队如何借助 Taotoken 统一管理多个原型项目的 AI API 成本

创业团队如何借助 Taotoken 统一管理多个原型项目的 AI API 成本 1. 多项目场景下的 API 成本管理挑战 小型创业团队在同时推进多个探索性项目时&#xff0c;往往需要根据项目特性选择不同的大模型能力。传统模式下&#xff0c;每个项目单独申请不同厂商的 API Key 会导致管理…

作者头像 李华
网站建设 2026/5/5 14:43:48

10分钟搞定Cellpose:AI细胞分割工具零基础安装配置秘籍

10分钟搞定Cellpose&#xff1a;AI细胞分割工具零基础安装配置秘籍 【免费下载链接】cellpose a generalist algorithm for cellular segmentation with human-in-the-loop capabilities 项目地址: https://gitcode.com/gh_mirrors/ce/cellpose 想要快速上手Cellpose这款…

作者头像 李华