简介:这份资源是《Visual Studio 2015(C#) Windows数据库项目开发》的配套资料包,面向具备C#基础、希望系统掌握Windows桌面端数据库应用开发的在校学生与初级开发者。内容围绕Visual Studio 2015与.NET Framework展开,涵盖ADO.NET数据访问、CRUD操作、DataSet与DataAdapter离线数据管理,以及多表查询、存储过程、触发器、视图、索引和数据库安全等进阶主题,并配有环境配置说明、实训项目、课件与教材案例,形成从环境搭建到项目实战的完整学习路径。压缩包共3423个文件,约95.9MB,以cs源码、resx与resources资源、dll类库、config配置、rdlc报表、aspx页面及ppt课件等为主,源码与课件相互印证,便于边学边练。目前已有1081人学习下载,适合需要借助完整项目案例巩固数据库开发技能、查漏补缺的读者参考。
1. 从一份 VS2015 的 C# 数据库项目包说起:它到底能跑通什么
如果你手上正好有一份 Visual Studio 2015(C#) Windows数据库项目开发.zip ,大概率是当年培训班的配套源码,或者某个企业内部练手项目的归档。这类包最典型的构成是:一个 .sln 解决方案、若干 .cs 窗体或控制台入口、一个 .mdf 或 .sql 脚本、以及 App.config 里的连接字符串。它解决的不是什么高深算法,而是把「C# 桌面端 + 本地/局域网数据库」这条最经典的增删改查链路完整跑起来——登录、查询、录入、修改、删除、报表导出,基本都在里面。
适合谁?一是刚学完 C# 语法、想找个能编译能点的完整项目练手的人;二是被派去维护老系统、需要快速看懂 ADO.NET 那套写法的在职工程师。不适合谁?想直接拿它上生产的人——VS2015 的工程默认目标框架多为 .NET Framework 4.5/4.6,SQL Server 版本也偏老,直接搬到新环境会有一堆兼容问题。所以这篇笔记的定位很明确:先让它在你机器上编译通过、数据库连上、功能点起来,再谈怎么改、怎么避坑。
2. 环境准备与工程结构拆解:先看清再动手
2.1 VS2015 工程在 Win10/Win11 上的安装取舍
VS2015 本体在较新的 Windows 上装起来是有玄学的。常见做法是不要直接双击 vs2015.ent_chs.iso 里的 vs_enterprise.exe ,而是先确认系统里没有残留更高版本的 Visual Studio Installer 服务。热词里那个「visual studio installer windows installer 服务不可用,请重启系统」的报错,八成是 Windows Installer 服务被占用或损坏,重启后以管理员身份运行安装器通常能过。
安装时组件勾选建议:
| 组件 | 是否必选 | 说明 |
|---|---|---|
| .NET Framework 4.5/4.6 目标包 | 必选 | 工程目标框架,缺了打不开 |
| SQL Server Data Tools | 必选 | 打开 .mdf 和 .sql 需要 |
| C# 语言支持 | 必选 | 默认勾选 |
| NuGet 包管理器 | 建议 | 补第三方库用 |
如果实在装不上 VS2015,退而求其次用 VS2019/2022 打开也行,但要在「重定目标解决方案」时把框架改到 4.6.1 以上,否则部分语法和引用会报错。这一步别偷懒,直接点「取消」保留 4.5 的话,后面编译报错会更多。
2.2 解压后先看这三个文件
解压 Visual Studio 2015(C#) Windows数据库项目开发.zip 之后,别急着双击 .sln 。先按顺序看三样东西:
第一, .sln 文件里 Project 段的路径,确认子项目目录结构,常见是 项目名/项目名.csproj 这种一层嵌套。第二, App.config 或 app.config 里的 connectionStrings 节点,这是数据库能不能连上的命门。第三,找 .sql 脚本或 .mdf 文件,判断数据库是「附加文件型」还是「脚本还原型」。
<!-- App.config 里典型的连接字符串,先看这一段 -->
<connectionStrings>
<add name="connStr"
connectionString="Data Source=.;Initial Catalog=MyDB;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
这段配置的含义: Data Source=. 表示本机默认实例, Initial Catalog 是数据库名, Integrated Security=True 走 Windows 身份验证。如果你的机器装的是 SQL Server Express,实例名要写成 .\SQLEXPRESS ,否则连不上。很多人卡在「登录失败」就是这里没改。
2.3 用 SQL Server 还原数据库的两种路径
如果包里是 .sql 脚本,直接在 SSMS 里新建查询、打开脚本、执行即可。如果是 .mdf 文件,走附加流程:SSMS 右键「数据库」→「附加」→「添加」→ 选中 .mdf 。附加失败最常见的原因是权限—— .mdf 所在目录没有给 SQL Server 服务账号读写权限。解决办法是把文件复制到 SQL Server 默认数据目录(如 C:\Program Files\Microsoft SQL Server\MSSQLXX.MSSQLSERVER\MSSQL\DATA )再附加。
-- 如果脚本里没有建库语句,先手动建一个
CREATE DATABASE MyDB
ON PRIMARY (
NAME = MyDB_data,
FILENAME = 'D:\SQLData\MyDB.mdf',
SIZE = 10MB,
FILEGROWTH = 5MB
)
LOG ON (
NAME = MyDB_log,
FILENAME = 'D:\SQLData\MyDB_log.ldf',
SIZE = 5MB,
FILEGROWTH = 5MB
);
建库时把 FILENAME 指到一个你有完全控制权限的目录,能省掉后面一堆权限报错。 FILEGROWTH 设 5MB 是保守值,练手够用,生产环境一般按数据量调大。
2.4 首次编译:把「引用黄色感叹号」清干净
打开 .sln 后,解决方案资源管理器里如果某个 References 下有黄色感叹号,说明引用路径失效。右键该引用 → 属性,看 HintPath 指向的 DLL 是否还在。常见缺失的是 System.Data.SQLite.dll 、 MySql.Data.dll 这类第三方驱动。缺哪个补哪个,用 NuGet 装对应版本比手动拷 DLL 稳。
# 如果工程用 NuGet,在包管理器控制台执行
Install-Package System.Data.SQLite -Version 1.0.113.0
Install-Package MySql.Data -Version 6.9.12
版本号别乱选,要和工程原本引用的版本对齐,否则会出现「找到的程序集清单定义与程序集引用不匹配」。装完重新生成解决方案,黄色感叹号消失、输出窗口显示「生成成功」,才算过了第一关。
3. 数据库连接与增删改查:把核心链路跑通
3.1 ADO.NET 连接对象的写法与参数
这类老项目基本都用 SqlConnection + SqlCommand 的原生 ADO.NET,而不是 Entity Framework。看懂这套写法,维护老系统就不慌。
// 典型的查询方法,注意 using 和参数化
public DataTable GetUsers(string keyword)
{
DataTable dt = new DataTable();
string sql = "SELECT Id, UserName, Age FROM Users WHERE UserName LIKE @kw";
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
// 参数化,防止拼接注入
cmd.Parameters.AddWithValue("@kw", "%" + keyword + "%");
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(dt);
}
}
return dt;
}
逻辑说明: using 保证连接和命令对象用完即释放,避免连接池耗尽。 AddWithValue 把用户输入作为参数传入,而不是字符串拼接,这是防 SQL 注入最基本的一步。 SqlDataAdapter.Fill 把结果灌进 DataTable ,绑定到 DataGridView 就能显示。参数 @kw 前后的 % 是模糊匹配通配符,如果做精确查询就去掉。
3.2 增删改的统一封装思路
老项目里增删改往往各写一个方法,重复代码多。可以抽一个 ExecuteNonQuery 封装:
public int ExecuteSql(string sql, params SqlParameter[] paras)
{
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
if (paras != null && paras.Length > 0)
cmd.Parameters.AddRange(paras);
conn.Open();
return cmd.ExecuteNonQuery(); // 返回受影响行数
}
}
}
调用时:
string sql = "UPDATE Users SET Age = @age WHERE Id = @id";
int rows = ExecuteSql(sql,
new SqlParameter("@age", 25),
new SqlParameter("@id", 1001));
ExecuteNonQuery 返回受影响行数, rows > 0 说明操作成功。参数用 SqlParameter 显式声明类型,比 AddWithValue 更可控,尤其是日期和 decimal 类型,能避免隐式转换报错。
3.3 用 SqlBulkCopy 做批量导入的注意点
热词里有人问「c# sqlbulkcopy 表变动有影响」,这确实是个坑。 SqlBulkCopy 按列名或序号映射,如果目标表结构变了(加列、改列序),映射就会错位。
using (SqlBulkCopy bulk = new SqlBulkCopy(connStr))
{
bulk.DestinationTableName = "Users";
// 显式指定列映射,别依赖默认顺序
bulk.ColumnMappings.Add("UserName", "UserName");
bulk.ColumnMappings.Add("Age", "Age");
bulk.BatchSize = 1000;
bulk.BulkCopyTimeout = 60;
bulk.WriteToServer(dt);
}
关键点: ColumnMappings 一定要显式写,源 DataTable 和目标表的列顺序不一致时,默认映射会串列。 BatchSize 控制每批提交行数,太大占内存,太小事务开销高,1000 到 5000 是常见区间。 BulkCopyTimeout 默认 30 秒,数据量大时调大。
3.4 事务处理:别让半截数据落库
涉及多表操作时,必须用事务包起来,否则中途失败会留下脏数据。
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlTransaction tran = conn.BeginTransaction())
{
try
{
using (SqlCommand cmd = new SqlCommand("INSERT INTO Orders ...", conn, tran))
{
cmd.ExecuteNonQuery();
}
using (SqlCommand cmd2 = new SqlCommand("UPDATE Stock ...", conn, tran))
{
cmd2.ExecuteNonQuery();
}
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
throw new Exception("下单失败,已回滚:" + ex.Message);
}
}
}
BeginTransaction 开启事务,所有 SqlCommand 都要带上 tran 参数,否则不在同一事务里。 Commit 提交, Rollback 回滚。注意 catch 里回滚后要把异常抛出去,别吞掉,否则上层不知道失败了。
4. 避坑与排查:那些年编译不过、连不上的血泪经验
4.1 现象:附加 .mdf 报「拒绝访问」
原因: .mdf 文件所在目录没有给 SQL Server 服务账号(通常是 NT SERVICE\MSSQLSERVER 或 NETWORK SERVICE )读写权限。
解决:右键 .mdf 所在文件夹 → 属性 → 安全 → 编辑 → 添加 → 输入 NETWORK SERVICE → 勾选「完全控制」→ 确定。或者干脆把文件移到 SQL Server 默认数据目录再附加。
4.2 现象:编译报「未能找到类型或命名空间名」
原因:目标框架版本不对,或者缺少对应程序集引用。比如工程用了 System.Data.SQLite ,但 NuGet 没装或版本不匹配。
解决:右键项目 → 属性 → 应用程序 → 目标框架,确认是 4.5 或 4.6。然后在 NuGet 里搜缺失的包,装与工程 packages.config 里一致的版本。如果 packages.config 里写的是 1.0.113.0 ,就别装 1.0.118.0 。
4.3 现象:连接字符串写 Data Source=. 报「找不到实例」
原因:本机装的是 SQL Server Express,实例名是 .\SQLEXPRESS ,不是默认实例。
解决:打开 SSMS,看连接对话框里的服务器名,或者运行 services.msc 看服务名。把连接字符串改成 Data Source=.\SQLEXPRESS;... 。如果用的是 LocalDB,写成 (localdb)\MSSQLLocalDB 。
4.4 现象:SqlBulkCopy 导入后数据串列
原因:目标表加了新列或调整了列顺序,而代码里没写 ColumnMappings ,默认按序号映射。
解决:显式添加 ColumnMappings ,源列名和目标列名一一对应。如果源 DataTable 列名和目标表列名一致,也可以直接 bulk.ColumnMappings.Add("列名", "列名") 。
4.5 现象:程序运行报「连接池已满」
原因: SqlConnection 没有及时释放,或者 DataReader 没关闭。
解决:所有 SqlConnection 、 SqlCommand 、 SqlDataReader 都用 using 包起来。 SqlDataReader 用完必须 Close 或 Dispose ,否则连接不会归还池。检查代码里有没有 conn.Open() 之后忘了 conn.Close() 的分支。
5. 进阶技巧:把老项目改造成可维护的样子
5.1 连接字符串抽到配置文件并加密
硬编码连接字符串是维护大忌。抽到 App.config 后,可以用 aspnet_regiis 加密,或者至少用 ConfigurationManager 读取。
// 读取 App.config 里的连接字符串
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
需要引用 System.Configuration 程序集。如果工程里没有,NuGet 装 System.Configuration.ConfigurationManager 。这样改数据库地址不用重新编译,改配置文件就行。
5.2 用 Dapper 替换手写 ADO.NET
如果不想大改架构,又想少写重复代码,可以引入 Dapper。它本质还是 ADO.NET,只是把映射自动化了。
using Dapper;
public List<User> GetUsers(string keyword)
{
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = "SELECT * FROM Users WHERE UserName LIKE @kw";
return conn.Query<User>(sql, new { kw = "%" + keyword + "%" }).ToList();
}
}
Query<User> 自动把结果集映射到 User 类,字段名和属性名一致即可。参数用匿名对象传,Dapper 自动转成 SqlParameter 。性能接近手写 ADO.NET,代码量少一半。注意 User 类的属性名要和查询列名对应,或者用 AS 别名。
5.3 验证改造是否成功的三个检查点
改完之后别急着交付,走一遍这三个检查:
| 检查点 | 方法 | 通过标准 |
|---|---|---|
| 连接可用 | 断开网络再连本机库 | 能正常查询 |
| 参数化生效 | 输入 ' OR '1'='1 测试 | 查不到数据,不报错 |
| 事务回滚 | 故意在第二句 SQL 写错表名 | 第一句数据不落库 |
这三个点过了,说明核心链路是稳的。尤其是第二个,很多人以为用了参数化就万事大吉,结果某处还在拼接字符串,一测就露馅。
5.4 我自己的习惯
从那以后我每次拿到这类老项目包,都强制走一遍「先还原数据库 → 再改连接字符串 → 再清引用 → 最后编译」的顺序,绝不跳步。因为跳过任何一步,后面报的错都会把你引到错误的方向,白白浪费半天。希望帮到你。
205



被折叠的 条评论
为什么被折叠?



