简介:这份资源面向C#与数据库开发的入门学习者,围绕Winform桌面程序如何连接SQL Server展开,同时覆盖网络连接与本地连接两种方式,帮助新手打通从界面搭建到数据读写的完整链路。压缩包共28个文件,约168KB,以cs源码、resx与resources资源文件、exe可执行程序、pdb调试符号为主,另含sln解决方案、csproj工程文件、sql查询脚本及说明文档,结构紧凑,便于直接打开运行和对照学习。内容涵盖连接字符串配置、ADO.NET核心组件使用、增删改查语句编写、app.config连接信息管理、异常处理与事务管理,以及DataGridView数据绑定等关键环节,并附有数据库查询语句与配置示例。目前已有2675人学习下载,适合希望快速掌握数据库驱动应用开发基础、需要可运行示例来验证与排错的初学者参考。
1. 从一次“连不上数据库”的翻车说起:这套 C# Winform + SQL Server 资源到底能帮你省多少事
很多新手第一次做 C# Winform 项目,卡住的地方往往不是界面拖控件,也不是按钮点击事件,而是程序一跑起来就弹出一个异常框——连不上数据库。更让人抓狂的是,同样的代码,在本地能跑,换台机器就报错;或者本地连接正常,改成网络连接就超时。这类问题排查起来像黑匣子,报错信息就那么一行,但原因可能藏在连接字符串、SQL Server 配置、防火墙、实例名、认证模式里的任何一个环节。
这份资源就是冲着这个痛点来的。它是一套完整的 C# Winform 连接 SQL Server 的示例工程,同时覆盖本地连接和网络连接两种模式,把增删改查四个基本操作的代码、数据库查询语句、数据库配置步骤都整理好了。适合刚接触 ADO.NET 的新手,也适合想快速搭一个可运行的数据管理界面的开发者。你拿到手之后,不用再从零去拼连接字符串,也不用去猜 SQL Server 该怎么配,照着走就能把环境跑通。
2. 本地连接和网络连接到底差在哪:连接字符串、认证模式与实例名
2.1 两种连接方式的本质区别
本地连接和网络连接,在代码层面体现为连接字符串的不同,但背后涉及的是 SQL Server 的实例发现机制和网络协议启用状态。本地连接通常走 Shared Memory 或 Named Pipes 协议,网络连接走 TCP/IP 协议。SQL Server 默认安装后,TCP/IP 协议可能是禁用的,这就是为什么你在本机用localhost或.能连上,换成局域网 IP 就失败。
连接字符串的核心参数有这几个:
| 参数 | 本地连接示例 | 网络连接示例 | 说明 |
|---|---|---|---|
| Data Source | .或(local)或localhost | 192.168.1.100或192.168.1.100,1433 | 网络连接需指定 IP 和端口 |
| Initial Catalog | MyTestDB | MyTestDB | 目标数据库名 |
| Integrated Security | True | True或False | Windows 认证还是 SQL 认证 |
| User ID / Password | 不需要 | sa/你的密码 | SQL 认证时需要 |
| Connect Timeout | 30 | 30 | 连接超时秒数,网络差可调大 |
本地连接字符串常见写法:
// 本地连接,使用 Windows 身份验证,连接本机默认实例 string localConnStr = "Data Source=.;Initial Catalog=MyTestDB;Integrated Security=True;Connect Timeout=30;";网络连接字符串常见写法:
// 网络连接,使用 SQL Server 身份验证,指定 IP 和端口 string remoteConnStr = "Data Source=192.168.1.100,1433;Initial Catalog=MyTestDB;User ID=sa;Password=YourPassword;Connect Timeout=60;";这里Data Source里的逗号后面跟的是端口号,默认实例是 1433,命名实例则用IP\实例名的形式。Integrated Security=True表示用当前 Windows 账户去认证,网络环境下如果对方机器不认识你的账户,就会失败,这时候要么改用 SQL 认证,要么在 SQL Server 里把你的 Windows 账户加进去。
2.2 网络连接前必须确认的三件事
在写代码之前,先确认 SQL Server 端已经准备好接受远程连接。这三步缺一不可:
第一步,打开 SQL Server 配置管理器,找到SQL Server 网络配置→实例的协议,把TCP/IP状态改为已启用。改完之后需要重启 SQL Server 服务。
第二步,双击TCP/IP进入属性,切到IP 地址选项卡,翻到最下面的IPAll,确认TCP 端口是1433。如果是命名实例,还要确认TCP 动态端口为空,否则端口会随机变。
第三步,在 Windows 防火墙里放行 1433 端口,或者直接放行 SQL Server 的程序。很多人卡在这里,代码没问题,就是防火墙把包拦了。
提示:如果用的是 SQL Server Express 版本,默认实例名可能是
SQLEXPRESS,连接字符串要写成Data Source=192.168.1.100\SQLEXPRESS,1433,并且 Express 版本默认可能没开 TCP/IP,需要手动启用。
2.3 认证模式的选择与切换
SQL Server 有两种认证模式:Windows 身份验证和混合模式。安装时如果选了 Windows 身份验证,后面想用sa账户登录是不行的,需要改回混合模式。改法是在 SSMS 里右键服务器 → 属性 → 安全性 → 选择SQL Server 和 Windows 身份验证模式,然后重启服务。
改完之后还要确认sa账户已启用。在 SSMS 里展开安全性→登录名,找到sa,右键属性 → 状态 → 登录改为已启用。如果sa密码忘了,可以用 Windows 认证登录进去重设。
-- 启用 sa 账户并设置密码(在 SSMS 里用 Windows 认证登录后执行) ALTER LOGIN sa ENABLE; ALTER LOGIN sa WITH PASSWORD = 'YourStrongPassword123';这两句 SQL 是很多新手会忽略的,光改认证模式不够,账户本身也得是启用状态。密码建议设复杂一点,因为sa是超级管理员,网络环境下暴露出去风险很高。如果只是内网测试,问题不大,但上线前一定要换掉。
3. 增删改查的代码落地:从 SqlConnection 到 SqlDataAdapter
3.1 封装一个可复用的数据库连接类
直接在窗体代码里写连接字符串,后期改起来很痛苦。常见做法是抽一个DbHelper类,把连接字符串放在配置文件里,代码只负责调用。这样本地和网络切换时,只改配置文件就行。
// DbHelper.cs using System; using System.Configuration; using System.Data; using System.Data.SqlClient; public static class DbHelper { // 从 App.config 读取连接字符串,方便本地/网络切换 private static readonly string ConnStr = ConfigurationManager.ConnectionStrings["MyDbConn"].ConnectionString; // 执行增删改,返回受影响行数 public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = new SqlConnection(ConnStr)) { using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (parameters != null && parameters.Length > 0) cmd.Parameters.AddRange(parameters); conn.Open(); return cmd.ExecuteNonQuery(); } } } // 执行查询,返回 DataTable public static DataTable ExecuteQuery(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = new SqlConnection(ConnStr)) { using (SqlDataAdapter adapter = new SqlDataAdapter(sql, conn)) { if (parameters != null && parameters.Length > 0) adapter.SelectCommand.Parameters.AddRange(parameters); DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } // 执行查询,返回首行首列 public static object ExecuteScalar(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = new SqlConnection(ConnStr)) { using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (parameters != null && parameters.Length > 0) cmd.Parameters.AddRange(parameters); conn.Open(); return cmd.ExecuteScalar(); } } } }ExecuteNonQuery用于 INSERT、UPDATE、DELETE,返回受影响的行数,可以用来判断操作是否成功。ExecuteQuery用SqlDataAdapter把结果填充到DataTable,适合绑定到 DataGridView。ExecuteScalar返回单个值,比如SELECT COUNT(*)。
参数用SqlParameter传,不要用字符串拼接。字符串拼接会有 SQL 注入风险,而且遇到日期、字符串里的单引号容易出错。用参数化查询,这两个问题都避免了。
3.2 App.config 里的连接字符串配置
连接字符串放在App.config里,切换本地和网络时只改这一处:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <!-- 本地连接 --> <add name="MyDbConn" connectionString="Data Source=.;Initial Catalog=MyTestDB;Integrated Security=True;Connect Timeout=30;" providerName="System.Data.SqlClient" /> <!-- 网络连接(切换时替换上面那条) --> <!-- <add name="MyDbConn" connectionString="Data Source=192.168.1.100,1433;Initial Catalog=MyTestDB;User ID=sa;Password=YourPassword;Connect Timeout=60;" providerName="System.Data.SqlClient" /> --> </connectionStrings> </configuration>注意providerName要写System.Data.SqlClient,这是 .NET Framework 下 SQL Server 的提供程序名。如果用的是 .NET Core 或 .NET 5+,提供程序名和包引用会不同,但这份资源面向的是 Winform 传统项目,用System.Data.SqlClient即可。
3.3 增删改查的具体实现
假设有一张学生表Students,字段为Id(主键,自增)、Name、Age、Class。下面是四个操作的代码。
新增:
// 新增一条学生记录 string sql = "INSERT INTO Students (Name, Age, Class) VALUES (@Name, @Age, @Class)"; SqlParameter[] ps = { new SqlParameter("@Name", "张三"), new SqlParameter("@Age", 20), new SqlParameter("@Class", "计算机一班") }; int rows = DbHelper.ExecuteNonQuery(sql, ps); // rows 为 1 表示插入成功删除:
// 按 Id 删除学生 string sql = "DELETE FROM Students WHERE Id = @Id"; SqlParameter[] ps = { new SqlParameter("@Id", 5) }; int rows = DbHelper.ExecuteNonQuery(sql, ps); // rows 为 0 表示没有找到对应记录修改:
// 按 Id 更新学生信息 string sql = "UPDATE Students SET Name = @Name, Age = @Age, Class = @Class WHERE Id = @Id"; SqlParameter[] ps = { new SqlParameter("@Name", "李四"), new SqlParameter("@Age", 21), new SqlParameter("@Class", "计算机二班"), new SqlParameter("@Id", 5) }; int rows = DbHelper.ExecuteNonQuery(sql, ps);查询:
// 查询所有学生,绑定到 DataGridView string sql = "SELECT Id, Name, Age, Class FROM Students ORDER BY Id DESC"; DataTable dt = DbHelper.ExecuteQuery(sql); dataGridView1.DataSource = dt;查询带条件时,同样用参数:
// 按班级查询 string sql = "SELECT Id, Name, Age, Class FROM Students WHERE Class = @Class"; SqlParameter[] ps = { new SqlParameter("@Class", "计算机一班") }; DataTable dt = DbHelper.ExecuteQuery(sql, ps); dataGridView1.DataSource = dt;ORDER BY Id DESC让最新插入的记录排在最前面,方便查看。绑定到DataGridView时,DataTable的列名会自动成为表头,如果想自定义表头,可以在DataGridView的Columns属性里设置,或者用AutoGenerateColumns = false手动加列。
3.4 数据库查询语句的补充说明
除了基本的增删改查,资源里还附了一些常用的查询语句,比如模糊查询、分页查询、聚合查询。这里挑两个典型的说一下。
模糊查询:
-- 查询名字里包含“张”的学生 SELECT Id, Name, Age, Class FROM Students WHERE Name LIKE '%' + @Keyword + '%';注意LIKE后面的通配符拼接方式,用参数传@Keyword,然后在 SQL 里拼%,这样既安全又灵活。不要写成LIKE @Keyword然后传%张%,虽然也能用,但参数值里带通配符容易混淆。
分页查询(SQL Server 2012 及以上):
-- 每页 10 条,取第 2 页 SELECT Id, Name, Age, Class FROM Students ORDER BY Id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;OFFSET和FETCH NEXT是 SQL Server 2012 引入的语法,比ROW_NUMBER()简洁。如果数据库版本低于 2012,就得用ROW_NUMBER()套子查询,资源里也有对应写法。
4. 避坑与排查:连接失败、超时、中文乱码的常见原因
4.1 报错“在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误”
现象:程序一运行就弹这个错,本地连接正常,网络连接必现。
原因:通常是 TCP/IP 协议没启用,或者端口不对,或者防火墙拦了。也有可能是 SQL Server 服务没启动。
解决:按 2.2 里的三步走一遍。先在配置管理器里启用 TCP/IP 并重启服务,再确认端口是 1433,最后检查防火墙。如果还不行,在命令行用telnet 192.168.1.100 1433测一下端口通不通,不通就是网络层的问题。
4.2 报错“用户 ‘sa’ 登录失败”
现象:连接字符串里用户名密码都对,就是登不上。
原因:sa账户没启用,或者认证模式还是仅 Windows,或者密码错了。
解决:用 Windows 认证登录 SSMS,执行ALTER LOGIN sa ENABLE;启用账户,再确认服务器属性里是混合模式。如果密码忘了,用ALTER LOGIN sa WITH PASSWORD = '新密码';重设。
4.3 连接超时,但本地测试正常
现象:本机用 SSMS 连远程库没问题,程序连就超时。
原因:连接字符串里Connect Timeout设得太短,或者网络延迟大,或者程序所在的机器和数据库之间的路由有问题。
解决:把Connect Timeout调到 60 或更大,先排除超时设置问题。如果还超时,在程序所在机器上用 SSMS 连一下,确认是不是程序环境的问题。有时候是程序的App.config没更新,还在用旧的连接字符串。
4.4 插入中文变成问号
现象:往数据库里插中文,查出来是???。
原因:数据库字段的排序规则不支持中文,或者连接字符串没指定字符集。
解决:建库时排序规则选Chinese_PRC_CI_AS,或者至少是支持 Unicode 的。字段类型用NVARCHAR而不是VARCHAR。连接字符串里一般不需要额外指定字符集,但如果用的是VARCHAR字段,插入中文就会丢。改成NVARCHAR后,参数类型也要对应,SqlParameter会自动处理。
4.5 DataGridView 绑定后不刷新
现象:增删改之后,DataGridView 还是旧数据。
原因:每次操作后没有重新查询绑定,或者绑定的 DataTable 没有重新赋值。
解决:在增删改成功后,重新调用查询方法,把新的 DataTable 赋给 DataSource。不要试图去修改原来的 DataTable,直接重新查一遍最简单。如果数据量大,可以考虑用BindingSource做增量更新,但新手项目直接重查就够了。
5. 进阶技巧:用配置文件切换本地与网络,以及连接测试的写法
5.1 在运行时切换连接字符串
有时候需要在程序里加一个选项,让用户自己选本地还是网络。做法是在App.config里放两条连接字符串,然后根据用户选择动态取。
<connectionStrings> <add name="LocalConn" connectionString="Data Source=.;Initial Catalog=MyTestDB;Integrated Security=True;" providerName="System.Data.SqlClient" /> <add name="RemoteConn" connectionString="Data Source=192.168.1.100,1433;Initial Catalog=MyTestDB;User ID=sa;Password=YourPassword;" providerName="System.Data.SqlClient" /> </connectionStrings>然后在代码里根据条件取:
// 根据用户选择切换连接字符串 string connName = radioButtonLocal.Checked ? "LocalConn" : "RemoteConn"; string connStr = ConfigurationManager.ConnectionStrings[connName].ConnectionString;但DbHelper里是静态读取的,要支持动态切换,可以把ConnStr改成属性,或者加一个SetConnectionString方法。更简单的做法是让DbHelper的方法接受连接字符串参数,但那样调用起来麻烦。折中方案是加一个静态字段,在程序启动时根据配置赋值。
5.2 写一个连接测试按钮
在窗体上加一个“测试连接”按钮,点一下就知道当前配置能不能连上。这个功能很实用,尤其是给不熟悉配置的人用。
private void btnTestConn_Click(object sender, EventArgs e) { try { using (SqlConnection conn = new SqlConnection(DbHelper.ConnStr)) { conn.Open(); MessageBox.Show("连接成功,SQL Server 版本:" + conn.ServerVersion); } } catch (Exception ex) { MessageBox.Show("连接失败:" + ex.Message); } }conn.ServerVersion会返回数据库版本号,能连上就说明配置没问题。如果失败,ex.Message里会有具体原因,比直接看异常堆栈直观。
5.3 用 try-catch 包裹数据库操作
数据库操作一定要加异常处理,不然程序直接崩。常见做法是在DbHelper的方法里加 try-catch,把异常往上抛,或者在调用处捕获。
try { int rows = DbHelper.ExecuteNonQuery(sql, ps); if (rows > 0) MessageBox.Show("操作成功"); else MessageBox.Show("没有影响到任何记录"); } catch (SqlException ex) { MessageBox.Show("数据库错误:" + ex.Message); } catch (Exception ex) { MessageBox.Show("系统错误:" + ex.Message); }SqlException是 SQL Server 相关的异常,比如主键冲突、字段不存在。Exception是兜底的。分开捕获可以针对不同错误给不同提示。
5.4 参数化查询的边界
参数化查询不是万能的,有些地方要注意。比如IN子句,不能直接写WHERE Id IN (@Ids)然后传一个逗号分隔的字符串,那样会被当成一个值。正确做法是动态拼参数,或者用表值参数。新手项目里,如果IN的列表是固定的,直接拼字符串也行,但要注意防注入。如果是用户输入的,就必须用参数。
另一个边界是LIKE,前面说过,通配符要拼在 SQL 里,参数只传关键词本身。
从那以后我每次配连接字符串,都先在本机用 SSMS 连一遍远程库,确认网络和认证没问题,再写进App.config。这样能把问题范围缩小到程序本身,而不是在代码和配置之间来回猜。希望帮到你。
本文还有配套的精品资源,点击获取