简介:一套基于 VB.NET 语言和 Access 数据库开发的 ASP.NET 汽车配件公司网站完整源码,面向 Web 开发初学者、计算机相关专业学生以及需要搭建小型电商展示平台的技术人员,能帮助快速理解 ASP.NET Web Forms 从页面设计、事件处理到数据访问的完整开发流程。压缩包采用 zip 格式,体积仅 127KB,资源内包含前台产品展示与分类搜索、购物车、订单提交与状态跟踪、用户注册登录,以及后台商品库存管理等核心模块的程序文件,既有网页界面,也有 VB.NET 业务逻辑代码和 Access 数据库表结构。目前已有 293 人学习下载,通过学习可以掌握 VB.NET 在 ASP.NET 中的事件驱动编程方式、ADO.NET 连接操作 Access 数据库的常用方法,以及 GridView、DetailsView 等数据绑定控件的典型使用技巧。此外,还能参考其母版页、用户控件和前端样式的组织方式,形成清晰的网站分层与复用设计思路,为后续学习 ASP.NET MVC 或 ASP.NET Core 打下扎实基础。
1. 这套 VB.net + Access 源码,为什么还值得花时间看
收到“ASP.NET源码——汽车配件公司网站(VB.net+Access数据库)源码.zip”这类压缩包,基本就是接手了一套 2008 到 2015 年间非常典型的中小企业站点:ASP.NET WebForms 做页面框架,VB.net 写在 .aspx.vb 和 App_Code 里,Access 数据库文件放在服务端某个目录,通过 OleDb 直接读写。这套组合放在今天的互联网语境里不算时髦,但在制造业、商贸公司的内部系统里仍有大量存量,业务越依赖旧代码,越没人敢轻易替换。
看这套代码的人通常有三类:被客户拉去维护旧系统的开发,刚进公司要接手老库存查询站点的运维,以及准备把它迁到 SQL Server 或 ASP.NET Core 的改造者。大家的共同点是先把源码“跑得起来、读得进去”,然后才谈得上改。下面按拿到压缩包后的真实顺序走一遍:解压、跑通、读懂数据访问、处理 Access 数据库本身,最后补齐上线前那几道安全工序。
2. 把压缩包变成能访问的站点:结构检查、IIS Express 与 Access 驱动
2.1 解压后先检查四个文件,判断源码完整度
拿到 zip 第一件事不是找 .sln 双击,而是先展开目录确认下面几样东西是否齐全:
CarPartsWeb/ ├─ CarParts.sln ├─ CarParts/ │ ├─ Default.aspx │ ├─ ProductList.aspx │ ├─ Admin/ │ │ ├─ ProductEdit.aspx │ │ └─ OrderList.aspx │ ├─ App_Data/ │ │ └─ CarParts.mdb │ ├─ App_Code/ │ │ ├─ DBUtil.vb │ │ └─ ProductDAL.vb │ ├─ Web.config │ └─ bin/ │ └─ *.dll对照目录做一次完整性检查,比后面花半小时猜路径问题要省事得多:
| 检查项 | 跑不起来的表现 | 常见处理 |
|---|---|---|
.sln/.vbproj | VS 打开提示不兼容或找不到项目 | 用“打开网站”指向 CarParts 文件夹,或用“打开项目”选 .vbproj |
Web.config | 站点报 500 或配置错误 | 备份原文件,补 connectionStrings 与 compilation 节点 |
App_Data\*.mdb | 首页能开,点列表页报“找不到文件” | 从备份恢复;确认连接串里的路径和文件名一致 |
App_Code\*.vb | 缺代码时页面直接编译失败 | 重建 DAL 类;没有 App_Code 的话,逻辑多半写在每个 .aspx.vb 里 |
很多人拿到手就双击 .sln,Visual Studio 弹出一堆升级提示,注意力反而被带偏。先确认这四样东西在不在、名字对不对,后面的问题会少一大半。
2.2 用 IIS Express 在本地把站点跑起来
如果本机装了 Visual Studio,最简单的方式是直接用 IIS Express 命令行启动,不经过 VS 调试器,跑起来最快,也方便定位是环境问题还是代码问题:
"C:\Program Files\IIS Express\iisexpress.exe" /path:E:\workspace\CarPartsWeb /port:8090参数说明:/path指到包含 Default.aspx 和 Web.config 的那一层,路径用反斜杠收盘符;/port避开 80 和 443 的已有占用,本地调试用 8090 基本不会冲突。启动后命令行会输出监听地址,浏览器访问http://localhost:8090即可。
老项目多针对 .NET Framework 2.0 或 4.0 编译,Windows 10/11 自带的 .NET Framework 4.x 对 4.0 站点是向后兼容的,通常不用额外装运行时。真正报错多集中在“加载类型 XXX 失败”,那往往是 App_Code 没有编译进 bin,或者网站目录少了一层。看到这个错,先回到 2.1 检查目录层级。
提示:站点放在用户目录或 E 盘根目录时,IIS Express 会在当前用户下以工作进程运行,首次访问要确认目录有“读取和执行”权限;如果复制到
C:\Program Files反而会被 UAC 挡住,不建议。
2.3 连接 Access 数据库:Jet 4.0 与 ACE 12.0 在 64 位系统上的差别
老代码里的连接串通常长这样:
<connectionStrings> <add name="AccessDB" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|App_Data\CarParts.mdb" providerName="System.Data.OleDb" /> </connectionStrings>先解释Provider=Microsoft.Jet.OLEDB.4.0的含义:这是 Windows 自带的 Jet 引擎,32 位时代几乎不需要额外安装。但到了 64 位 Windows 10/11,Jet 4.0 驱动虽然还在,64 位进程默认却加载不了,而 IIS Express 在多数较新版本里以 64 位运行,于是报“未在本地计算机上注册 Microsoft.Jet.OLEDB.4.0”的概率非常高。
常见的落地解法有两种。第一种是把连接串换成 ACE 引擎:
<connectionStrings> <add name="AccessDB" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=E:\workspace\CarPartsWeb\App_Data\CarParts.mdb" providerName="System.Data.OleDb" /> </connectionStrings>Microsoft.ACE.OLEDB.12.0来自微软官方发布的 Access Database Engine 可再发行组件,64 位系统装 64 位版本即可在 64 位进程里使用。Data Source建议写绝对路径,避免|DataDirectory|在不同宿主进程里解析不一致。第二种是保留 Jet 4.0,强制 IIS 以 32 位模式跑:
C:\Windows\System32\inetsrv\appcmd.exe set app "Default Web Site/CarParts" /enabled32BitAppOnWin64:true这两种解法挑哪一种?我一般优先用 ACE 引擎,因为它同时解决 mdb 和 accdb 两种文件的读取,而且调整 IIS 应用池位数的操作在部分托管服务器上没有管理员权限可执行。改完连接串后记得重启站点,OleDb 驱动是进程启动时加载的,配置改完不生效多半就是这个原因。
3. 读懂 VB.net 源码:App_Code 分层、事件驱动与数据绑定
3.1 先分清哪些是界面、哪些是逻辑、哪些是数据访问
汽车配件网站这种规模的 WebForms 项目,目录结构通常就暴露了作者的分层意图。典型的组织方式是这样:
CarPartsWeb/ ├─ *.aspx / *.aspx.vb # UI 层,控件与事件 ├─ App_Code/ │ ├─ DBUtil.vb # 数据库连接与命令封装 │ ├─ ProductDAL.vb # 数据访问层(DAL) │ ├─ CategoryDAL.vb │ └─ OrderBLL.vb # 业务层(BLL) └─ Web.config # 连接串、编译与运行时配置理解这套代码,关键是不要把“ASP.NET”想成一个整体,而是拆成三层:.aspx负责页面长什么样,.aspx.vb里的Page_Load、Button_Click负责响应事件,App_Code里的类负责读写数据库。最常见的维护错误是:页面出错了先去改 SQL,实际上报错往往在 DAL 层的数据类型转换,或者 UI 层绑定的字段名不一致。
读的顺序我一般建议从DBUtil.vb开始。它是连接串和数据库命令的公共入口,能一眼看出项目用的是 OleDb 还是 SqlClient、参数是写死还是拼串、有没有统一关闭连接。这三件事基本决定了后面所有维护工作的改法。
3.2 DAL 的常规写法:DataTable 返回,而不是 DataReader
老项目的数据访问层几乎都是同一个模板:
Imports System.Data.OleDb Public Class DBUtil Public Shared Function GetConnection() As OleDbConnection Dim connStr As String = ConfigurationManager.ConnectionStrings("AccessDB").ConnectionString Return New OleDbConnection(connStr) End Function End ClassPublic Function GetHotProducts() As DataTable Dim sql As String = "SELECT TOP 10 ProductId, ProductName, UnitPrice FROM Products WHERE IsHot = True" Using conn As OleDbConnection = DBUtil.GetConnection() Using da As New OleDbDataAdapter(sql, conn) Dim dt As New DataTable() da.Fill(dt) Return dt End Using End Using End Function补充说明几个细节:Using保证了OleDbConnection和OleDbDataAdapter在方法退出时释放,这是老代码里最容易被删掉的部分;DataAdapter.Fill是一次性把结果读到内存的DataTable,所以方法结束后连接已经关闭,页面绑定数据时不再占用数据库连接。这种“方法内开、方法内关”的写法,配合 Access 的单文件数据库模型,在并发量不大时是最简单可靠的做法。
3.3 参数化与字符串拼接:老代码里最该警惕的一处
这类源码里被问得最多的是查询怎么写。老项目里经常为了省事,出现WHERE ProductName Like '%" & txtKeyword.Text & "%'"这样的拼接。内部系统这么跑着没问题,一旦站点暴露到公网,参数值直接进入 SQL 文本,隐患非常大。改法是全部换成参数化:
Dim sql As String = "SELECT ProductId, ProductName FROM Products WHERE ProductName LIKE '%' + @kw + '%'" Using conn As OleDbConnection = DBUtil.GetConnection() Using cmd As New OleDbCommand(sql, conn) cmd.Parameters.AddWithValue("@kw", keyword) conn.Open() Using reader As OleDbDataReader = cmd.ExecuteReader() While reader.Read() Dim pid As Integer = CInt(reader("ProductId")) ' 组装列表项 End While End Using End Using End UsingAddWithValue的作用是把keyword作为参数传给数据库引擎,而不是拼进 SQL 字符串。这里有一个 Access 特有的坑:Jet/ACE 的 LIKE 通配符默认是*,但参数值里写的是 SQL Server 风格的%。在 Access 里LIKE '%abc%'不会按预期工作,正确写法是LIKE '*abc*',或者用ALIKE关键字走 ANSI 模式。很多 Access 老系统的搜索功能时好时坏,原因就在这里。
| 场景 | Access 写法 | SQL Server 写法 |
|---|---|---|
| 模糊匹配 | LIKE '*abc*' | LIKE '%abc%' |
| 空值处理 | IsNull(x, '') | ISNULL(x, '') |
| 当前时间 | Date() | GETDATE() |
| 字符串连接 | a & b | a + b或CONCAT(a, b) |
3.4 页面事件模型与数据绑定
最后落到网页层。首页或产品列表页最常见的骨架是这样:
<asp:Repeater ID="rptProducts" runat="server"> <ItemTemplate> <h3><%# Eval("ProductName") %></h3> <span><%# Eval("UnitPrice", "{0:C}") %></span> </ItemTemplate> </asp:Repeater>对应的后置代码:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load If Not IsPostBack Then BindProducts() End If End Sub Private Sub BindProducts() Dim dal As New ProductDAL() rptProducts.DataSource = dal.GetHotProducts() rptProducts.DataBind() End SubIsPostBack判断是不是回发:第一次加载页面时绑定数据,点击按钮提交后不再重复绑定,否则用户输入框里的值会被刷新掉。Eval写在模板里,做的是反射式取值,字段名要和 SQL 返回的列名一致,拼错一个字母页面直接报DataBinding异常。遇到这类报错,先看列名,再看DataTable是不是空,别急着查数据库连接。
4. Access 数据库:读 mdb、理清表关系与迁移到 SQL Server
4.1 用 OleDb 列出 mdb 里的所有表
打开 mdb 文件,很多人的第一反应是用 Access 软件。如果机器上没装 Office,写几行代码读结构更快:
Using conn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=E:\workspace\CarPartsWeb\App_Data\CarParts.mdb") conn.Open() Dim schemaTable As DataTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"}) For Each row As DataRow In schemaTable.Rows Response.Write(row("TABLE_NAME") & "<br/>") Next End Using这里的原理是:OleDbSchemaGuid.Tables告诉 OLEDB 提供者返回“表”而不是“视图”“系统表”,第四个参数"TABLE"限定只取用户表。为什么不用SELECT * FROM MSysObjects?因为 Access 的系统表默认对普通用户不可读,权限不足时会直接抛异常,GetOleDbSchemaTable走的是驱动内部接口,不碰权限问题。
读出来的表名一般是Products、Categories、Orders、OrderDetails。汽车配件站点的核心关系通常是:Categories(CategoryId, CategoryName)一侧,Products(ProductId, CategoryId, ProductName, UnitPrice, StockQty)多侧,订单相关两张表记录头与明细。理解了这个关系,再看代码里的 JOIN 就能对上了。
4.2 Access 数据类型与 SQL Server 的字段映射
如果要迁移或者重新建查询,第一件事是把 Access 的老类型映射到 SQL Server:
| Access 字段类型 | 常见 SQL Server 类型 | 迁移后要注意的事 |
|---|---|---|
| 文本(255) | nvarchar(255) | 长度要逐列确认,别全按 255 |
| 备注 | nvarchar(max) | 大文本,索引前先减长度 |
| 自动编号 | int IDENTITY(1,1) | 插入后要取回 ID 用 SCOPE_IDENTITY() |
| 数字(长整型) | int | 主键与外键的 int 要能对上 |
| 是/否 | bit | 不要用 True/False 比较,用 1/0 |
| 日期/时间 | datetime2 | Access 允许空日期,SQL Server 有 1900 下限,清洗数据时注意 |
对照完类型再回头看 VB 代码,会发现大量CInt(dr("CategoryId"))的原因:Access 返回的数字列经常是Int32或Decimal,绑定到控件前不做转换,显示结果就容易“失踪”。这类转换代码不是多余的,保留它们,迁移后反而省事。
4.3 页面检索:一类 SQL 两类数据库的写法差异
配件网站一定有搜索框。最常见的按分类和关键字筛选,在 Access 里的原生写法是:
SELECT ProductId, ProductName, UnitPrice FROM Products WHERE Status = @st AND ProductName LIKE '%' + @kw + '%' ORDER BY ProductId DESC;配上 VB.net 调用:
Dim sql As String = "SELECT ProductId, ProductName, UnitPrice FROM Products " & _ "WHERE Status = @st AND ProductName LIKE '%' + @kw + '%' ORDER BY ProductId DESC" Using conn As OleDbConnection = DBUtil.GetConnection() Using cmd As New OleDbCommand(sql, conn) cmd.Parameters.AddWithValue("@st", status) cmd.Parameters.AddWithValue("@kw", keyword) conn.Open() Using reader As OleDbDataReader = cmd.ExecuteReader() ' ... End Using End Using End Using为什么这么写能兼容两头?因为%在 Jet 4.0 的ALIKE语法里也能匹配,把它放进参数字符串里,比改 SQL 里的*更稳妥。真正不兼容的是 Access 独有的IIF、NZ,以及&连接运算符(在 SQL Server 里&是位运算),这些语法在迁库时必须逐一改掉。
4.4 把 Access 数据迁到 SQL Server 的完整步骤
迁库的常见做法不是手工建表再逐条复制,而是用微软官方工具 SSMA for Access:
| 步骤 | 具体操作 | 常见失败点 |
|---|---|---|
| 1. 备份 | 复制一份 .mdb,确认没有进程占用 | 文件正被 IIS 锁定时复制会失败 |
| 2. 安装 SSMA | 从微软官网下载 SSMA for Access,版本与目标 SQL Server 匹配 | 先装 SQL Server 再装 SSMA,顺序反了可能找不到实例 |
| 3. 转换 | 新建迁移项目,连接 mdb 和 SQL Server,执行 Convert 后再 Migrate | 自动编号与默认值最容易丢,迁移后逐表检查 |
| 4. 校验 | 对每张表跑SELECT COUNT(*)对比行数 | 备注字段里的换行符偶尔会变形 |
| 5. 改连接串 | 把 web.config 的 OleDb 换成 SqlClient | 别忘了同时改providerName,只改连接文本不够 |
改完连接串,应用里的 SQL 还要过一次适配。最容易忽略的是IIF(IsNull(...))要改成ISNULL,Date()要改成GETDATE(),&拼接要改成+。连接串如下:
<connectionStrings> <add name="MainDB" connectionString="Server=.;Database=CarParts;User Id=sa;Password=YourPassword;" providerName="System.Data.SqlClient" /> </connectionStrings>参数说明:Server=.表示本机默认实例;Database是迁移后的库名;providerName必须从System.Data.OleDb改成System.Data.SqlClient,否则代码里所有New OleDbConnection的地方仍会用错驱动。迁移后第一次点击页面,报错集中在“对象名无效”和“列名无效”,多数是表名或列名大小写、下划线差异导致的,处理方法是批量替换 SQL 里的表名。
5. VB.net + Access 老站点上线前:补 ViewState 加密、关调试开关
5.1 给 web.config 补上机器密钥与 ViewState 加密
访问量不大不表示可以裸奔。老 WebForms 页面的 ViewState 默认用 base64 编码存储,不加密也不做完整性校验,页面里能看到很多业务数据的编码结果。常见做法是显式配置 machineKey 并打开加密:
<system.web> <machineKey validation="HMACSHA256" validationKey="你的48字节hex密钥" decryption="AES" decryptionKey="你的32字节hex密钥" /> <pages viewStateEncryptionMode="Always" viewStateMac="true" /> </system.web>参数说明:validation与validationKey负责校验 ViewState 有没有被篡改,decryption与decryptionKey负责加密内容,两个 Key 可以用 IIS 管理器的“机器密钥”功能生成。这组配置还有一层作用:ViewState 中如果被塞入精心构造的序列化数据,且 MAC 校验缺失,就可能在回发时被反序列化利用;开启viewStateMac并指定machineKey后,服务端校验不过直接拒绝,等于关掉了这条路径。要注意 Key 别用网上公开的示例值,也別在负载均衡环境里让各服务器各自生成,否则回发时会报“验证视图状态 MAC 失败”。
5.2 在 Global.asax 里记录异常,并关掉调试开关
站点已经在跑、又在改代码的时候,最怕访问者只看得到 500,你这边啥也看不到。加一段最轻量的全局异常日志:
Protected Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Error Dim ex As Exception = Server.GetLastError() If ex IsNot Nothing Then Dim path As String = Server.MapPath("~/App_Data/error.log") IO.File.AppendAllText(path, Now.ToString("yyyy-MM-dd HH:mm:ss") & " " & ex.ToString() & vbCrLf) End If End SubApplication_Error在每次未处理异常时触发,Server.GetLastError()拿到原始异常,AppendAllText把堆栈追加到日志文件。上线前最后再改两个 web.config 项:把compilation debug设为false,把customErrors mode设为RemoteOnly,远程用户看到的是友好错误页,本机调试时仍能看到完整堆栈,信息不会全丢。
改完这两段配置,web.config 一保存,ASP.NET 会回收应用进程。这时访问一次首页,看 App_Data 下有没有生成 error.log;如果页面上没有异常但日志也没生成,说明没有触发全局错误,可以临时在 Page_Load 里抛一个异常验证链路。如果你接手的压缩包里没有 Global.asax,把上面这段复制进去,保存配置后访问首页,错误日志会直接告诉你真正坏在哪一行。
本文还有配套的精品资源,点击获取