资讯详情

C# Winform 连接 SQL Server 实战:本地与网络连接及增删改查

📅 2026/10/20 3:13:03 | 华诺云谱 👁 阅读
C# Winform 连接 SQL Server 实战:本地与网络连接及增删改查
简介这份资源面向C#与数据库开发的入门学习者围绕Winform桌面程序如何同时实现SQL Server的本地连接与网络连接并完成增删改查这一核心场景展开。包内共28个文件以cs源码、resx与resources资源文件、exe可执行程序、pdb调试文件为主另附sql脚本、sln解决方案、csproj工程文件及说明文档压缩包约168KB结构完整可直接运行调试。资源中给出了数据库连接字符串的写法、ADO.NET中SqlCommand与DataAdapter的用法以及INSERT、DELETE、UPDATE、SELECT四类语句的落地示例还涉及app.config配置、异常处理与事务管理、DataGridView数据绑定等实用知识点。目前已有2675人学习下载适合刚接触C# Winform与SQL Server、希望快速跑通一套可复用增删改查模板的新手参考。1. 从一次“连不上数据库”的翻车说起这个 Winform 项目到底能干什么很多新手写 C# Winform 连 SQL Server代码在自己电脑上跑得好好的一换机器就报“登录失败”或者“找不到服务器”。问题往往不在 C# 本身而是连接字符串写死了本地实例名或者 SQL Server 的远程连接没打开。这个项目就是冲着这类场景来的它用一套 Winform 界面同时演示了本地连接和网络连接两种 SQL Server 访问方式并把增删改查四个操作完整落地。适合刚学完 C# 基础、想找一个能直接跑起来的数据库练手项目的开发者。项目里附了建库建表的 SQL 语句和数据库配置说明拿到源码后不用自己猜表结构照着配就能跑。下面按“项目结构 → 两种连接方式 → 增删改查实现 → 避坑 → 二次开发”的顺序拆一遍。2. 项目结构与技术选型Winform ADO.NET 直连 SQL Server2.1 为什么是 ADO.NET 而不是 Entity Framework这个项目的定位是“适合新手”所以数据访问层没有引入 ORM而是直接用System.Data.SqlClient命名空间下的SqlConnection、SqlCommand、SqlDataAdapter。原因很实际新手需要看清一条 SQL 从 C# 发到数据库再拿回结果的全过程ORM 会把这段链路藏起来。项目里每个按钮对应一个独立方法方法内部就是“打开连接 → 构造命令 → 执行 → 关闭连接”四步没有多余封装。等你把 ADO.NET 这套跑熟了再去用 Dapper 或 EF 会顺很多。技术栈清单如下层次技术说明界面Winform拖拽控件事件驱动数据访问ADO.NETSqlConnection / SqlCommand / SqlDataAdapter数据库SQL Server本地实例或局域网实例配置App.config存放连接字符串语言C#.NET Framework 项目2.2 目录结构长什么样项目解压后大致是这样一个结构不同版本可能略有差异但核心文件跑不掉项目根目录/ ├── 数据库脚本/ │ ├── CreateDatabase.sql -- 建库建表语句 │ └── InitData.sql -- 初始测试数据 ├── 源码/ │ ├── App.config -- 连接字符串配置 │ ├── MainForm.cs -- 主窗体逻辑 │ ├── MainForm.Designer.cs -- 界面控件定义 │ └── DbHelper.cs -- 数据库操作封装类 └── 说明.txt -- 配置步骤DbHelper.cs是核心把连接字符串读取、连接打开关闭、执行增删改查的方法都放在这里。MainForm.cs只负责调DbHelper的方法并把结果绑到 DataGridView 上。这种分层对新手友好界面归界面数据库归数据库改一处不影响另一处。2.3 连接字符串放在 App.config 里连接字符串不写死在代码里这是项目里一个值得保留的习惯。App.config里加一段configuration connectionStrings !-- 本地连接Data Source 用 . 或 (local) -- add nameLocalConn connectionStringData Source.;Initial CatalogTestDB;Integrated SecurityTrue providerNameSystem.Data.SqlClient/ !-- 网络连接Data Source 换成局域网 IP -- add nameRemoteConn connectionStringData Source192.168.1.100;Initial CatalogTestDB;User IDsa;Password你的密码 providerNameSystem.Data.SqlClient/ /connectionStrings /configurationData Source.表示本机默认实例Integrated SecurityTrue表示用 Windows 身份验证不用输账号密码。网络连接那条把Data Source换成目标机器的 IP并且用 SQL Server 账号验证。改连接方式时只动配置文件不用重新编译代码。3. 两种连接方式落地本地连接和网络连接的代码差异3.1 本地连接Windows 身份验证怎么配本地连接的前提是 SQL Server 装在本机并且当前 Windows 用户有访问权限。代码里读取配置并打开连接// 从 App.config 读取本地连接字符串 string connStr ConfigurationManager .ConnectionStrings[LocalConn].ConnectionString; using (SqlConnection conn new SqlConnection(connStr)) { try { conn.Open(); // 打开连接 // 连接成功后可以执行查询 MessageBox.Show(本地连接成功); } catch (SqlException ex) { // 常见错误登录失败、找不到实例 MessageBox.Show(连接失败 ex.Message); } }ConfigurationManager需要引用System.Configuration程序集。using语句保证连接用完自动释放不用手动调Close()。如果这里报“无法打开登录所请求的数据库”先去 SSMS 里确认TestDB存在并且当前 Windows 账号在 SQL Server 的登录名列表里。3.2 网络连接远程访问要过的三道关网络连接比本地多三个配置点缺一个都连不上第一SQL Server 要开启 TCP/IP 协议。在 SQL Server 配置管理器里找到“SQL Server 网络配置 → 实例的协议”把 TCP/IP 状态改为“已启用”然后重启 SQL Server 服务。第二防火墙要放行 1433 端口。默认实例监听 1433如果改过端口连接字符串里要加,端口号比如Data Source192.168.1.100,1433。第三SQL Server 要允许 SQL 账号登录。在 SSMS 里把服务器属性 → 安全性 → 服务器身份验证改为“SQL Server 和 Windows 身份验证模式”并确保sa账号已启用。// 网络连接用 SQL 账号验证 string remoteStr ConfigurationManager .ConnectionStrings[RemoteConn].ConnectionString; using (SqlConnection conn new SqlConnection(remoteStr)) { conn.Open(); // 后续操作和本地连接完全一致 }代码层面本地和网络没有任何区别差异全在连接字符串和服务器配置上。这也是为什么项目要把两种连接分开演示让新手明白“连不上”多半不是 C# 代码的问题。3.3 连接测试按钮的实现主窗体上一般会放一个“测试连接”按钮点一下分别测本地和远程private void btnTest_Click(object sender, EventArgs e) { // 依次测试两个连接字符串 string[] names { LocalConn, RemoteConn }; foreach (string name in names) { string cs ConfigurationManager .ConnectionStrings[name].ConnectionString; using (SqlConnection conn new SqlConnection(cs)) { try { conn.Open(); MessageBox.Show(name 连接成功); } catch (Exception ex) { MessageBox.Show(name 失败 ex.Message); } } } }这个按钮的价值在于把“配置对不对”和“增删改查逻辑对不对”分开排查。连接都过不了后面的查询代码不用看。4. 增删改查核心实现从 SQL 语句到 DataGridView 绑定4.1 查询SqlDataAdapter 填充 DataTable查询用SqlDataAdapter最省事它自动把结果集填进DataTable再绑到DataGridViewpublic DataTable QueryAll() { DataTable dt new DataTable(); string sql SELECT Id, Name, Age, Dept FROM Student; using (SqlConnection conn new SqlConnection(connStr)) { // SqlDataAdapter 内部自动打开和关闭连接 SqlDataAdapter adapter new SqlDataAdapter(sql, conn); adapter.Fill(dt); } return dt; }adapter.Fill(dt)执行查询并把结果写入dt。界面里调用dataGridView1.DataSource dbHelper.QueryAll();DataGridView的列名会自动对应SELECT里的字段名。如果想让列标题显示中文可以在SELECT里用AS起别名比如SELECT Name AS 姓名。4.2 新增参数化 INSERT 防止注入新增用SqlCommand的ExecuteNonQuery返回受影响行数。关键是必须用参数化查询不要拼字符串public int AddStudent(string name, int age, string dept) { string sql INSERT INTO Student (Name, Age, Dept) VALUES (Name, Age, Dept); using (SqlConnection conn new SqlConnection(connStr)) { SqlCommand cmd new SqlCommand(sql, conn); // 参数化值通过 Parameters 传入不拼进 SQL cmd.Parameters.AddWithValue(Name, name); cmd.Parameters.AddWithValue(Age, age); cmd.Parameters.AddWithValue(Dept, dept); conn.Open(); return cmd.ExecuteNonQuery(); // 返回插入的行数 } }AddWithValue会自动推断参数类型简单场景够用。如果字段类型严格可以用Add(Age, SqlDbType.Int).Value age显式指定。返回值大于 0 表示插入成功。4.3 修改和删除靠主键定位修改和删除都要带WHERE条件通常用主键Idpublic int UpdateStudent(int id, string name, int age, string dept) { string sql UPDATE Student SET NameName, AgeAge, DeptDept WHERE IdId; using (SqlConnection conn new SqlConnection(connStr)) { SqlCommand cmd new SqlCommand(sql, conn); cmd.Parameters.AddWithValue(Id, id); cmd.Parameters.AddWithValue(Name, name); cmd.Parameters.AddWithValue(Age, age); cmd.Parameters.AddWithValue(Dept, dept); conn.Open(); return cmd.ExecuteNonQuery(); } } public int DeleteStudent(int id) { string sql DELETE FROM Student WHERE IdId; using (SqlConnection conn new SqlConnection(connStr)) { SqlCommand cmd new SqlCommand(sql, conn); cmd.Parameters.AddWithValue(Id, id); conn.Open(); return cmd.ExecuteNonQuery(); } }界面上选中DataGridView某一行从CurrentRow.Cells[Id].Value取出主键再调对应方法。执行完重新查询一次刷新表格这是最简单的同步方式。4.4 建库建表 SQL 脚本项目附带的CreateDatabase.sql大致如下先建库再建表-- 建库 CREATE DATABASE TestDB; GO USE TestDB; GO -- 建表 CREATE TABLE Student ( Id INT IDENTITY(1,1) PRIMARY KEY, -- 自增主键 Name NVARCHAR(50) NOT NULL, Age INT, Dept NVARCHAR(50) ); GO -- 插入测试数据 INSERT INTO Student (Name, Age, Dept) VALUES (N张三, 20, N计算机), (N李四, 21, N电子);IDENTITY(1,1)让Id自动增长插入时不用管。NVARCHAR支持中文前面加N表示 Unicode 字符串。在 SSMS 里新建查询把这段贴进去执行即可。5. 避坑与排查连接失败、中文乱码、更新不生效5.1 报“在与 SQL Server 建立连接时出现与网络相关的错误”现象本地能连换台机器或连局域网就报这个。原因通常是 TCP/IP 没启用、防火墙拦了 1433、或者Data Source写的是主机名但解析不到。解决先在目标机器上用telnet IP 1433测端口通不通不通就去开协议和防火墙Data Source直接写 IP别写计算机名。5.2 报“用户 ‘sa’ 登录失败”现象连接字符串账号密码看着没错就是登不上。原因多半是sa账号被禁用或者服务器还是“仅 Windows 身份验证”模式。解决用 Windows 身份登录 SSMS服务器属性里改成混合模式再到安全性 → 登录名里把sa启用并重设密码最后重启 SQL Server 服务。5.3 插入中文变成问号现象INSERT进去的中文在数据库里显示???。原因是字段类型用了VARCHAR而不是NVARCHAR或者 SQL 字符串前没加N。解决建表时中文列统一用NVARCHAR插入语句写成VALUES (N张三, ...)。5.4 修改后 DataGridView 没变化现象点了修改按钮数据库确实改了但表格还是旧数据。原因是DataGridView绑的是之前查询出来的DataTable不会自动刷新。解决每次增删改成功后重新调一次QueryAll()并重新赋给DataSource。这是最直接的做法数据量小的时候完全够用。5.5 忘记释放连接导致连接池耗尽现象程序跑一段时间后报“超时时间已到但是未能从连接池获取连接”。原因是SqlConnection没关。解决所有连接都用using包起来保证Dispose被调用。SqlDataAdapter.Fill内部会自己开关连接但SqlCommand手动Open的必须手动关用using最省心。6. 二次开发把直连改成分层架构和可配置切换这个项目跑通之后最值得做的改造是把数据库操作从窗体里抽出来做成独立的数据访问层并且让本地/网络连接可以运行时切换。我一般会这样改新建一个IDbService接口定义QueryAll、Add、Update、Delete四个方法然后写一个SqlServerDbService实现它。窗体只依赖接口不直接碰SqlConnection。这样以后想换成 MySQL 或者加一个 SQLite 本地缓存只需要再写一个实现类窗体代码一行不用动。连接切换可以做成下拉框选中后把对应的连接字符串名存到一个静态变量里DbService每次取连接字符串时读这个变量public static class DbConfig { // 当前使用的连接名默认本地 public static string CurrentConnName LocalConn; } // DbService 内部取连接字符串 string cs ConfigurationManager .ConnectionStrings[DbConfig.CurrentConnName].ConnectionString;窗体上放一个ComboBox选项是“本地连接”和“网络连接”SelectedIndexChanged里改DbConfig.CurrentConnName然后重新查询刷新表格。这样不用改配置文件也不用重启程序就能切换数据源。另一个实用改造是给查询加条件过滤。现在QueryAll是全表查数据一多表格就卡。可以在界面上加一个文本框和一个查询按钮把SELECT改成带WHERE Name LIKE Keyword的形式public DataTable QueryByName(string keyword) { DataTable dt new DataTable(); string sql SELECT Id, Name, Age, Dept FROM Student WHERE Name LIKE Keyword; using (SqlConnection conn new SqlConnection(connStr)) { SqlDataAdapter adapter new SqlDataAdapter(sql, conn); // 前后加 % 实现模糊匹配 adapter.SelectCommand.Parameters.AddWithValue( Keyword, % keyword %); adapter.Fill(dt); } return dt; }LIKE配合参数化同样能防注入%在参数值里拼不要拼进 SQL 文本。这个改动很小但能让项目从“演示”变成“能用”。最后说一个我踩过的坑早期我把连接字符串直接写在DbHelper的常量里换台机器就要改代码重新编译。后来统一挪到App.config部署时只改配置文件省了很多事。从那以后我每次新建 Winform 数据库项目第一件事就是把连接字符串抽到配置文件并且本地和远程各留一条切换只改一个名字。希望这个项目能帮你把 ADO.NET 这套流程跑顺后面再上 ORM 会轻松很多。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑