ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

C#学生成绩管理系统开发实战:Access数据库与ADO.NET完整解析

C#学生成绩管理系统开发实战:Access数据库与ADO.NET完整解析 简介一份完整的C#学生成绩管理系统课程设计源码包面向计算机相关专业正在完成数据库课程设计或练习C# WinForm开发的初学者。项目以Access作为后端数据库通过ADO.NET完成数据交互覆盖学生、课程、成绩三大模块的增删改查并包含登录窗体、数据验证、try-catch异常处理等典型教学细节。压缩包共90个文件以31个cs源文件、11个resx资源文件为主另含可运行exe、DLL依赖库及1个accdb示例数据库整体大小仅3.35MB可用Visual Studio直接打开调试。已有962人学习浏览源码中包含建表语句与示例数据可以直观看到学生、课程、成绩三张表如何通过外键关联UI部分使用TextBox、ComboBox、DataGridView等控件适配了菜单事件与数据绑定方式。目录结构清晰便于对照源码理解从数据库设计、SQL命令执行到界面绑定的完整流程也可作为课程作业答辩前的查漏补缺参考。1. 学生成绩管理系统课程作业里最值得拆开的经典骨架如果你是一个正在做C#课程设计的学生应该对“学生成绩管理系统”这个题目不陌生——它几乎是大二、大三《数据库应用》和《面向对象程序设计》课程的标配大作业。第一次拿到这个题目时我也觉得“不就是写个增删改查嘛”。但真正动手后才发现这个系统其实是C#编程、数据库设计、UI界面、数据校验、异常处理五件事的组合体而作业拿高分和拿及格分的差距恰恰藏在这些组合的细节里。这套课程作业C#学生成绩管理系统源码包本质是一个可以完整运行的Windows Forms项目采用的方案是C# .NET Framework Access数据库。有学生表、课程表、成绩表三张核心数据表覆盖了从登录验证到成绩录入、查询统计的完整闭环。它的价值不在功能多而在“麻雀虽小、五脏俱全”——身份证级的表结构、OleDb数据访问、DataGridView绑定这些企业项目的标配技术你都能在这份代码里看到实际用法。适合有C#语法基础、但第一次做数据库项目的初学者照着改、照着抄也适合想快速搞清WinForms数据绑定和ADO.NET套路的同学参考。2. 表结构与ADO.NET动手前先把Access这块地基打稳2.1 三张表怎么设计才能不违反范式课程设计要求“遵循第一范式及以上”我见过不少同学把所有信息塞进一张大表结果改个课程名称要更新几十行记录。这套系统的表结构是很标准的第三范式做法核心是学生、课程、成绩三张独立表再通过外键关联。学生表放静态属性课程表放教学计划成绩表才放分数这个动态数据。成绩表不直接存学生姓名和课程名称而是存StudentID和CourseID两个外键查询时再用JOIN把名字带出来。这样设计的好处是学生转专业改姓名只动学生表不会污染历史成绩课程改名也同理成绩数据永久稳定。建表SQL我用Access的SQL视图写给你看这段代码在Access查询设计器里改成“SQL视图”模式可以直接执行CREATE TABLE Students ( StudentID TEXT(10) PRIMARY KEY, StudentName TEXT(20) NOT NULL, Gender TEXT(2), BirthDate DATETIME, ClassName TEXT(30) ); CREATE TABLE Courses ( CourseID TEXT(10) PRIMARY KEY, CourseName TEXT(50) NOT NULL, Credits SINGLE, CourseType TEXT(20) ); CREATE TABLE Scores ( ScoreID AUTOINCREMENT PRIMARY KEY, StudentID TEXT(10) NOT NULL, CourseID TEXT(10) NOT NULL, Score SINGLE, CONSTRAINT FK_Scores_Student FOREIGN KEY (StudentID) REFERENCES Students(StudentID), CONSTRAINT FK_Scores_Course FOREIGN KEY (CourseID) REFERENCES Courses(CourseID) );这套建表语句里有个关键的命名选择ScoreID用AUTOINCREMENT自增主键而不是用“学生课程”联合主键。联合主键理论上能防止一个学生同一门课录两次成绩但实际开发中业务上经常需要修改成绩记录或者保留补考、重修等多条记录所以单列自增主键更灵活唯一性保证交给业务层的校验代码去做。字段类型上用TEXT定长而不是VARCHAR也是Access的老传统——Access中的TEXT类型默认大小255短文本场景不需要用MEMO长文本类型。2.2 连接字符串的32位与64位玄学Access数据库在C#里通过OleDb连接连接字符串看起来就一行但这一行里藏着本系统最容易翻车的坑。常见写法是这个string connStr ProviderMicrosoft.ACE.OLEDB.12.0;Data Source|DataDirectory|\StudentScore.mdb;;如果你的开发环境是Visual Studio 项目根目录下的Access文件用|DataDirectory|这个宏能自动定位到项目的App_Data文件夹或者bin\Debug目录比写死绝对路径要稳得多。但注意这行代码假设你已经装了Access数据库引擎。64位Windows上跑你大概率需要去微软官网下载“Microsoft Access Database Engine 2010 Redistributable”并且安装时要用命令行指定/passive参数否则它会拒绝安装在Office已存在的老版本上。另一个老项目遗留问题早期代码里普遍写ProviderMicrosoft.Jet.OLEDB.4.0。这个驱动的本质是32位组件在64位系统上无论怎么设置平台目标都会报“未找到提供程序”这是最经典的翻车现场。我的习惯是直接用ACE.OLEDB.12.0并且把项目的“平台目标”改成x86保持32位模式运行避开Office和Access驱动混装时的兼容性黑洞。2.3 ADO.NET分层DataAdapter、DataSet与DataTable的分工C#访问Access数据库走的是ADO.NET这套老牌数据访问模型很多新手把连接、命令、数据适配器写在一个按钮事件里代码又臭又难维护。这套系统里做了基础分层UI层只和DataTable打交道数据访问层通过DataAdapter把SQL结果填充到内存中的DataTable然后绑定给DataGridView。using System.Data; using System.Data.OleDb; public static class DbHelper { private static string connStr ProviderMicrosoft.ACE.OLEDB.12.0;Data Source|DataDirectory|\StudentScore.mdb;; public static DataTable ExecuteQuery(string sql, params OleDbParameter[] parameters) { using (OleDbConnection conn new OleDbConnection(connStr)) using (OleDbCommand cmd new OleDbCommand(sql, conn)) { if (parameters ! null) { cmd.Parameters.AddRange(parameters); } OleDbDataAdapter da new OleDbDataAdapter(cmd); DataTable dt new DataTable(); da.Fill(dt); return dt; } } public static int ExecuteNonQuery(string sql, params OleDbParameter[] parameters) { using (OleDbConnection conn new OleDbConnection(connStr)) using (OleDbCommand cmd new OleDbCommand(sql, conn)) { conn.Open(); if (parameters ! null) { cmd.Parameters.AddRange(parameters); } return cmd.ExecuteNonQuery(); } } }我一般会建议把连接字符串统一抽到App.config里但课程作业的代码往往追求“直接能跑”所以这段写在静态类里更省事理解起来也直观。ExecuteQuery负责返回结果集给界面显示ExecuteNonQuery负责执行增删改操作并返回受影响行数。注意using语句的作用OleDbConnection和OleDbCommand都是非托管资源的封装离开作用域就自动释放这是初学阶段最容易漏的细节。DataAdapter有个隐藏行为值得留意——它内部会自动打开和关闭连接所以ExecuteQuery方法里不需要显式调用conn.Open()。而ExecuteNonQuery必须手动Open因为命令执行依赖一个已建立的连接状态。在我带过的学生项目里分不清这两者的区别是导致“偶尔报错、偶尔正常”的最常见原因。3. 登录模块与核心CRUD每个功能都值得认真读一遍3.1 登录验证参数化查询写进课程作业登录界面是几乎所有系统评分的第一个功能点但很多课程作业在这里暴露了“SQL拼接”的坏习惯。文本框里输入的内容直接拼进SQL字符串一旦输入 OR 11就能绕过密码直接登录初学者亲手做出来的系统往往连这种安全隐患都不自知。所以这个系统的登录代码哪怕要抄也建议从参数化查询开始抄。private void btnLogin_Click(object sender, EventArgs e) { string username txtUsername.Text.Trim(); string password txtPassword.Text; if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) { MessageBox.Show(用户名和密码不能为空, 提示); return; } string sql SELECT COUNT(*) FROM Users WHERE UserName name AND UserPwd pwd; DataTable dt DbHelper.ExecuteQuery(sql, new OleDbParameter(name, username), new OleDbParameter(pwd, password)); if (Convert.ToInt32(dt.Rows[0][0]) 0) { this.Hide(); MainForm main new MainForm(username); main.Show(); } else { MessageBox.Show(用户名或密码错误, 登录失败); } }注意两个关键点第一SQL里出现的是name、pwd占位符而不是直接拼接的字符串第二密码字段用SELECT COUNT(*)而不是把整行数据查出来再对比逻辑更简洁。OleDbParameter构造函数第一个参数必须和SQL里的占位符名字完全一致包括符号。这是OleDb和SqlClient的一个小差异——SqlClient可以用也可以不用OleDb是严格匹配位置和名字的。另外注意一个课程作业里普遍存在的做法问题我也是直到工作后写企业项目才把密码改成哈希存储课程作业里明文密码也能接受但至少别把登录成功的验证逻辑写成“查得到就过”要明确分支处理。3.2 学生管理的增删改查四段代码覆盖Button事件全流程学生管理模块是这个系统的重头戏基本功能是列表展示、新增、修改、删除。列表展示用DataGridView数据源绑定刚才说的DataTable新增和修改共用一个输入窗体靠一个标志区分是Insert还是Update操作。新增学生的核心逻辑是这样private void btnAddStudent_Click(object sender, EventArgs e) { string studentId txtStudentId.Text.Trim(); string name txtName.Text.Trim(); string gender cmbGender.SelectedItem?.ToString() ?? ; string className txtClass.Text.Trim(); if (string.IsNullOrEmpty(studentId) || string.IsNullOrEmpty(name)) { MessageBox.Show(学号和姓名为必填项, 验证提示); return; } string checkSql SELECT COUNT(*) FROM Students WHERE StudentID id; DataTable checkResult DbHelper.ExecuteQuery(checkSql, new OleDbParameter(id, studentId)); if (Convert.ToInt32(checkResult.Rows[0][0]) 0) { MessageBox.Show(该学号已存在请勿重复添加, 添加失败); return; } string sql INSERT INTO Students (StudentID, StudentName, Gender, ClassName) VALUES (id, name, gender, class); int rows DbHelper.ExecuteNonQuery(sql, new OleDbParameter(id, studentId), new OleDbParameter(name, name), new OleDbParameter(gender, gender), new OleDbParameter(class, className)); if (rows 0) { MessageBox.Show(学生添加成功, 完成); LoadStudentList(); } }这段代码里有三个常规细节值得强调一是先查重再插入虽然理论上存在并发窗口但课程作业场景下完全够用二是cmbGender.SelectedItem?.ToString() ?? 处理了下拉框未选中时的空值问题这是C# 6.0之后很实用的写法三是执行成功后调用LoadStudentList()刷新表格刷新方法内部会重新执行SELECT * FROM Students并重新绑定DataGridView。修改操作的UPDATE语句类似但WHERE条件必须用原始学号而这个学号在编辑模式下要锁定不可修改。实现方式是在修改窗口加载时把主键传入一个私有字段SQL里where条件使用该字段值而与界面文本框无关防止用户在编辑时顺手改了学号导致主键冲突。删除操作同理通过DataGridView的CurrentRow获取单元格值再执行DELETE。这里要处理一个特殊情况学生被删除前需要判断其在成绩表中是否有记录否则外键会变成悬挂引用。常见的做法是先查Scores表存在记录就提示“该学生已有成绩记录不能直接删除”或者级联删除成绩记录。3.3 查询统计模块组合条件拼SQL最怕空值学生的成绩查询是这个系统的另一个评分点。往往要求支持按学号、按姓名模糊查询、按课程查询甚至按分数段筛选。很多初学者在一个查询按钮里堆各种if判断把SQL拼得支离破碎。我的做法是构造动态参数列表用List收集条件最后组成Where子句。private void btnSearch_Click(object sender, EventArgs e) { string sql SELECT s.StudentID AS 学号, s.StudentName AS 姓名, c.CourseName AS 课程名称, sc.Score AS 成绩 FROM Students s INNER JOIN Scores sc ON s.StudentID sc.StudentID INNER JOIN Courses c ON sc.CourseID c.CourseID WHERE 11; ListOleDbParameter paramList new ListOleDbParameter(); if (!string.IsNullOrEmpty(txtKeyword.Text.Trim())) { sql AND (s.StudentName LIKE kw OR s.StudentID LIKE kw); paramList.Add(new OleDbParameter(kw, % txtKeyword.Text.Trim() %)); } if (cmbCourse.SelectedIndex ! -1) { sql AND c.CourseName course; paramList.Add(new OleDbParameter(course, cmbCourse.SelectedItem.ToString())); } if (!string.IsNullOrEmpty(txtMinScore.Text.Trim())) { sql AND sc.Score minScore; paramList.Add(new OleDbParameter(minScore, Convert.ToInt32(txtMinScore.Text))); } DataTable result DbHelper.ExecuteQuery(sql, paramList.ToArray()); dgvResult.DataSource result; }这段代码里的WHERE 11看着像废话实际是老开发的标准套路——它让后续所有条件拼接都能直接用AND开头代码结构统一。需要注意LIKE操作符SQL Server里通配符是%Access里也支持%但不能用*这是Access一个极容易踩的位置在查询设计器里默认用的是*但ODBC和OleDb驱动传SQL时用%。分数段的查询把文本框值Convert后再拼参数而不是直接拼接字符串既防注入又能在输入非数字时触发异常被try-catch捕获后提示“请输入数字”。4. DataGridView与数据验证把界面操作焊在数据链路里4.1 DataGridView绑定DataTable之后还要改三件事DataGridView是这个系统主要的数据展示控件。数据绑定最简洁的方法是直接给DataSource赋值dgvStudents.DataSource dt;但直接绑定后会有三个“不好看”的问题列标题显示英文原名、列宽不自动适应、行头不显示序号。课程作业的界面分往往从这里拉开差距。我习惯在绑定后立即设置列属性dgvStudents.AutoGenerateColumns false; DataGridViewTextBoxColumn colId new DataGridViewTextBoxColumn(); colId.DataPropertyName StudentID; colId.HeaderText 学号; colId.Width 100; DataGridViewTextBoxColumn colName new DataGridViewTextBoxColumn(); colName.DataPropertyName StudentName; colName.HeaderText 姓名; colName.Width 130; dgvStudents.Columns.Add(colId); dgvStudents.Columns.Add(colName);AutoGenerateColumns false是关键它告诉控件“不要自动按字段名生成列”改由你手动定义这样中文表头、列宽、只读属性都在掌控中。DataPropertyName映射到数据源里的字段名HeaderText是显示在界面上的文字两者分离是DataGridView的典型用法。删除和编辑还要获取当前选中行写一句string selectedId dgvStudents.CurrentRow.Cells[StudentID].Value.ToString();这里有个隐藏坑CurrentRow在某些情况下会是null——比如点击了列头导致选中状态变化或者绑定数据源为空时。稳妥的做法是先判断dgvStudents.CurrentRow ! null再取Cells。另外如果你定义了多列隐藏字段比如编辑时需要用主键但不想显示可以通过colId.Visible false隐藏取值依然通过Columns[StudentID]访问。4.2 成绩录入分数范围、下拉联动和单元格校验三板斧成绩录入界面的评分点主要看数据验证。成绩必须限制在0~100之间。处理方式有硬校验和软校验两种硬校验在写入数据库前拦截软校验在控件层面就阻止非法输入。课程作业至少需要做到硬校验。private void btnSaveScore_Click(object sender, EventArgs e) { if (cmbStudent.SelectedIndex -1 || cmbCourse.SelectedIndex -1) { MessageBox.Show(请先选择学生和课程, 提示); return; } if (!double.TryParse(txtScore.Text.Trim(), out double score)) { MessageBox.Show(成绩必须为数字, 格式错误); return; } if (score 0 || score 100) { MessageBox.Show(成绩必须在0到100之间, 范围错误); return; } string sql UPDATE Scores SET Score score WHERE StudentID sid AND CourseID cid; string studentId cmbStudent.SelectedValue.ToString(); string courseId cmbCourse.SelectedValue.ToString(); int rows DbHelper.ExecuteNonQuery(sql, new OleDbParameter(score, score), new OleDbParameter(sid, studentId), new OleDbParameter(cid, courseId)); if (rows 0) { sql INSERT INTO Scores (StudentID, CourseID, Score) VALUES (sid, cid, score); DbHelper.ExecuteNonQuery(sql, new OleDbParameter(sid, studentId), new OleDbParameter(cid, courseId), new OleDbParameter(score, score)); } }一个值得注意的细节这里用Update先执行检查受影响行数如果返回0说明该组合不存在再转Insert。这就是“有则改、无则增”的Merge逻辑避免了一张成绩表同时存在重复记录的问题。下拉框绑定学生和课程列表时用DisplayMember和ValueMember分别设置显示文本和值字段。绑定后SelectedValue拿的就是StudentIDSelectedItem拿的是整行DataRowView这一区别在代码中容易混淆。还有一种是运行时单元格级校验DataGridView自带的CellValidating事件可以在用户编辑单元格时实时校验Cancel为true则强制焦点停留。但课程作业场景里我建议把这个机制用在“期末成绩修改”窗体中简单实现即可不需要做的太复杂评分老师更看重业务规则是否完整而不是UI交互的炫技。4.3 数据验证的边界条件别只拦空值还要拦类型和长度谈到数据验证很多学生的代码风格是这样的if为空就报错if为null就return。但对于一个要“能跑、能演示、能答辩”的课程作业验证至少要覆盖三种情况必填项不能为空、类型要正确、长度要符合数据库字段定义。Access的TEXT(10)如果插入超过10个字符会因为数据溢出直接抛异常——这种异常如果不处理界面就会崩给老师看。我习惯在帮助类里写一个ValidateInputs方法集中做基础合法性判断private static bool ValidateStudentInfo(string studentId, string name, out string errorMsg) { if (string.IsNullOrEmpty(studentId)) { errorMsg 学号不能为空; return false; } if (studentId.Length 10) { errorMsg 学号长度不能超过10位; return false; } if (string.IsNullOrEmpty(name)) { errorMsg 姓名不能为空; return false; } if (name.Length 20) { errorMsg 姓名长度不能超过20位; return false; } errorMsg string.Empty; return true; }这样的集中校验放在业务层而不是UI层好处是无论登录窗口、管理窗口还是成绩窗口调用同一套规则不会出现“这里校验了那里没校验”的不一致。成绩的范围检查用double.TryParse配合边界判断学号统一用Trim()去掉首尾空格这些基本功写进代码里后答辩时被问“为什么这么设计”你也答得出来。5. 避坑手记Access C# 课程作业最常见的七个报错与解法5.1 “未在本地计算机上注册 Microsoft.ACE.OLEDB.12.0 提供程序”这是C#连接Access时最高频的报错没有之一。现象代码运行到new OleDbConnection就抛异常。原因机器上没有安装Access Database Engine或者安装了32位但你的项目编译成了AnyCPU/×64。解决下载安装AccessDatabaseEngine.exe并在Visual Studio的项目属性里把“平台目标”改为x86。这两个操作缺一不可。如果装完仍然报错检查控制面板是否同时存在2007和2010两个版本的驱动高版本没有覆盖掉低版本导致注册表混乱用命令行卸载重装一次全搞定。5.2 SQL语句语法错误操作符丢失现象一切看起来都正常但执行复杂查询时突然报“FROM子句中语法错误”或“操作符丢失”。原因多半是把SQL Server的语法习惯带到了Access。最常见的是日期写法用了GETDATE()而不是NOW()字符串用了ISNULL()但Access里是NZ()。解决本系统涉及的字段比较简单出现问题时优先检查表名和字段名是否包含了保留字比如Name、Date、Level这类词汇在Access里都可能是保留字。万不得已就改成[Name]、[Date]加方括号包裹。5.3 数据库文件被占用无法写入现象程序运行中你想手动用Access打开.mdb文件检查数据提示“文件正在使用中”。原因OleDbConnection没有及时释放或者连接池里还挂着旧连接。这个现象在Access里尤其明显因为它本质上是文件型数据库。解决代码里所有的Connection、Command、DataAdapter都写在using块里保证Dispose执行。如果还是有占用那就是DataAdapter的Fill操作不释放连接——在ExecuteQuery里DataAdapter用完同样要调用Dispose。纯课程作业场景还可以把所有OleDbConnection对象改成局部变量而不是类级别的私有字段用一点、开一点、关一点。5.4 DataGridView显示列中文名乱码或空白现象绑定完DataSource后列标题显示为字段名或者干脆一列空白的。原因没有关闭AutoGenerateColumns手动添加的列DataPropertyName又写错了字段名。字段名是大写还是小写Access里不敏感但拼写错误是实打实的。解决把绑定数据的SQL里用AS别名比如SELECT StudentID AS 学号, StudentName AS 姓名然后设置AutoGenerateColumns true这样列标题直接显示中文省掉手动定义列的代码。缺点是列宽不可控需要再遍历Columns设置一遍Width。5.5 修改记录时不报错但数据库里根本没变化现象点击“保存”按钮提示“修改成功”重新查询一看数据还是原来的。原因典型的问题是这个系统里存在两个数据源。学生列表的DataGridView绑定的是DataTable你修改了DataGridView里的单元格但没有把改动推回数据库。解决DataGridView直接编辑单元格默认不会自动执行UPDATE语句。正确做法是点击“修改”按钮时把当前行对应的主键取出来用主键作为WHERE条件再显式执行UPDATE。这也是这套系统里Update按钮的核心逻辑——把DataGridView的CurrentRow当作用户输入载体而不是数据修改载体。5.6 模糊查询结果和查询设计器看到的不一致现象同一句SQL在Access查询设计器里执行出结果在C#程序里查出来却是空表。原因查询设计器有“所见即所得”的保护层比如自动加引号、自动转换数据类型。而OleDb是直接把字符串交给驱动一个字符的偏差都会导致整个SQL失效。最典型的就是LIKE通配符查询设计器接收*OleDb必须使用%。解决所有SQL都以字符串形式在C#环境中测试不依赖查询设计器做验证。调试时把完整的SQL和每个参数值打印到输出窗口或写入日志文件会极大缩短排查时间。我用过的最粗暴有效的方式是在DbHelper里加一行Debug.WriteLine(sql);每次执行前输出最终语句然后把这个语句复制到Access里单独跑一遍。5.7 程序在别的机器上打开数据库路径找不到现象在自己的电脑上编译好的exe拷到别的电脑上双击运行登录界面都出不来报“找不到数据库文件”。原因代码里写死了绝对路径比如D:\study\StudentScore.mdb拷贝过去路径自然不存在。解决确保连接字符串使用|DataDirectory|\StudentScore.mdb格式并在App.config中配置好DataDirectory指向。程序在Visual Studio里调试、部署、拷到U盘换台电脑跑都不会出现路径断裂的问题。这是我工作后学会的第一个小技巧也是课程作业里最容易被忽视的移植性问题。6. 再进一步把课程作业升级成答辩稳过的完整项目如果你的作业已经能跑通增删改查但想让它站在“优秀”区间有三个低成本的小改动值得做。第一给所有按钮的Click事件统一包一层try-catch在catch里记录异常并展示友好提示。第二把数据库里的Users表密码字段改成MD5哈希值存库登录时先把用户输入做哈希再比对这一句话就能在答辩时成为亮点。第三添加一个“成绩统计”功能用一条SQL完成按课程计算平均分、最高分、及格率。统计功能的核心SQL长这样SELECT CourseName AS 课程名称, AVG(Score) AS 平均分, MAX(Score) AS 最高分, MIN(Score) AS 最低分, SUM(IIF(Score 60, 1, 0)) / COUNT(*) * 100 AS 及格率 FROM Scores INNER JOIN Courses ON Scores.CourseID Courses.CourseID GROUP BY CourseName;IIF函数是Access特别好用的条件统计函数一行顶替SQL Server里的CASE WHEN。放在一个窗体的DataGridView里展示就足以撑起整个“查询统计”模块的演示时长。另外一个加分项是给DataGridView添加导出Excel功能虽然用Office COM组件需要额外引用但代码量不大、演示效果直观两个方法加几行循环就能完成。使用时注意先判断机器有没有装Excel没装就提示改用导出CSV文件方案。最后说一个我的习惯课程作业写完我会把整个项目文件夹里的bin\Debug和obj目录删掉让项目干干净净地压缩存档。这样换台电脑用Visual Studio打开时所有引用从头编译一遍反而比带着一堆残留dll、容易触发版本冲突要好得多。源码包和Access数据库文件放同一个目录数据库文件我习惯在项目根目录下建一个Data文件夹专门归置。从那以后我每次提交课程设计、毕业设计、甚至给同事转交接项目都强制自己先清一遍临时目录再打压缩包。这个习惯帮我把“能跑”的项目变成“换一台机器也能跑”的项目。希望帮到你。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表