You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# DataGridView加载记录过慢,Dapper操作SQL性能优化咨询

问题根因分析
  • 异步写法完全无效:现有LoadProduct方法将数据库查询逻辑全部包裹在Invoke委托内,所有查询操作仍在UI线程执行,Task.Run仅增加了线程调度开销,没有起到后台加载的作用,和直接绑定数据源的性能表现完全一致。
  • SQL查询性能波动:数据缓存命中时(SQL Server将常用数据加载到内存缓冲池、执行计划缓存存在),查询速度很快;如果缓存失效(执行计划被回收、数据从内存中换出),SQL需要重新编译查询、从磁盘读取数据,就会出现10秒以上的延迟,这是你遇到时快时慢的核心原因。
  • DataGridView渲染开销高:直接将携带完整图片字节数组的列表绑定到控件,绑定时会一次性将所有图片字节数组解码为可渲染的图像对象,数据量稍大就会阻塞UI线程。
  • 属性映射不匹配:Product类中价格属性名为Price,但SQL查询和插入的字段为ComboPrice,虽然数据库大小写不敏感的情况下可以勉强映射,但会增加Dapper的映射开销,甚至可能出现字段赋值失败的问题。
  • 图片读取逻辑存在缺陷:插入图片时仅调用一次stream.Read,该方法不保证一次性读取全部流内容,极易出现图片存储不完整的问题。
优化方案

1. 修正异步加载逻辑

将数据库查询放到后台线程执行,仅绑定数据源时切回UI线程:

public async void LoadProduct()
{
    // 后台执行查询,不阻塞UI
    var products = await Task.Run(() => db.GetProduct());
    // 仅UI绑定操作在主线程执行
    dataGridView1.DataSource = products;
}

2. 优化数据库查询性能

  • 建立覆盖索引,避免全表扫描,提升查询稳定性:
CREATE NONCLUSTERED INDEX IX_Table_Products_Query ON Table_Products (Name)
INCLUDE (Image, ComboPrice);
  • 数据量大于50条时增加分页逻辑,每次仅查询当前页需要显示的10-20条数据,大幅降低数据传输和渲染开销。
  • 优化Dapper查询配置,开启非缓冲读取降低内存占用,同时统一字段映射:
public List<Product> GetProduct()
{
    // 直接复用静态连接字符串,不要每次新建Connection实例
    using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(静态连接字符串))
    {
        // 字段别名保证和Product属性名匹配,关闭缓冲降低内存开销
        return connection.Query<Product>("SELECT Name, Image, ComboPrice AS Price FROM Table_Products", buffered: false).ToList();
    }
}

3. 优化插入逻辑

  • 修复图片读取不全的问题,直接用内存流拷贝全量数据:
private void Insert_Click(object sender, EventArgs e)
{
    byte[] photo;
    using (var stream = File.OpenRead(txtPhoto.Text))
    using (var ms = new MemoryStream())
    {
        stream.CopyTo(ms);
        photo = ms.ToArray();
    }
    db.InsertProduct(txt_description.Text, photo, Convert.ToDecimal(txt_price.Text));
}
  • 简化插入代码,不需要额外创建List对象:
public void InsertProduct(string name, byte[] image, decimal price)
{
    using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(静态连接字符串))
    {
        connection.Execute(
            "INSERT INTO Table_Products(Name, Image, ComboPrice) VALUES(@Name, @Image, @ComboPrice)", 
            new { Name = name, Image = image, ComboPrice = price }
        );
    }
}

4. 优化DataGridView渲染

  • 开启DataGridView的双缓冲、虚拟模式,仅渲染当前可见行的内容。
  • 优先将图片存储到本地磁盘,数据库仅存储图片路径,查询时仅拉取文本数据,需要显示图片时再异步加载对应路径的文件,可将查询速度提升90%以上。

内容的提问来源于stack exchange,提问作者Aaric Aaiden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 02:06:10