资讯动态

VB.NET连接MySQL完整实战:从mysql_connect到MySqlConnection

发布时间:2026/10/13 14:40:40 来源:尧图企业网站定制
简介这是一份基于VB.NET的MySQL连接与注册登录演示项目面向VB初学者以及需要快速验证MySQL连接逻辑的开发者。压缩包内共15个文件以多个VB窗体与业务模块源码为核心配合resx资源、sln解决方案和vbproj工程文件结构完整且体量小巧仅17KB可在Visual Studio中直接打开查看。项目实现了通过MySQL连接组件连通数据库并完成用户注册与登录的常见流程也涉及连接字符串配置、界面事件处理、连接失败判断与基础排错思路。已有215人学习下载对正在学习桌面端数据库开发的读者有参考价值从中可大致梳理出小型数据访问项目的目录组织方式以及如何在VB项目中调用MySQL驱动完成增删改查前的基础连接验证。1. 这个 rar 里装的不是 PHP 教程一个 VB.NET 的 MySQL 连接工程搜索 mysql connect 或 mysql_connect 时绝大多数教程讲的是 PHP 老接口mysql_connect(localhost, user, pass)。但这个压缩包解压后你会看到Form1.vb、MySQL_Connection_Project.vbproj、MySQL_RegisterLogin.vb——这是一个 Visual Basic .NET 的 Windows Forms 工程不是 PHP 脚本。换句话说mysql_connect在这里不是一个 PHP 函数而是 MySQL 连接 这个动作的工程名底层用的是 .NET 的MySqlConnection连接对象。这个包解决的是最实际的诉求在 VB.NET 桌面程序里把 MySQL 连上并实现一个带注册和登录界面的完整示例。文件里bin/Debug、bin/Release、obj/x86这些目录说明它已经在 x86 平台下编译过属于能直接打开跑的工程而不是散落的代码片段。适合两类人一是刚接触 VB.NET MySQL 的学生需要一个完整窗体项目当参照二是手头有老 WinForms 项目、想把数据库迁移到 MySQL 的开发者。接下来我会按 连接方式选型 → 环境配置 → 注册登录模块 → 踩坑 → 封装进阶 的顺序把它拆开讲。2. mysql connect 的三种姿势Connector/NET、ODBC 与历史遗留的 mysql_connect先把这个工程里最容易被绕晕的概念讲清楚。mysql_connect这个写法在 PHP 5.2 时代是标准答案接收服务器地址、用户名、密码三个参数返回连接标识符。但 PHP 5.5 起它被标记为废弃PHP 7.0 直接移除官方要求改用mysqli或 PDO。摘要里大量篇幅讲mysql_connect、mysqli_connect、new PDO()严格说那是 PHP 场景而这个压缩包里的源码用的是 VB.NET对应的是MySql.Data.MySqlClient.MySqlConnection类。网上很多下载站会把描述文案混着写所以先把这个对应关系立住后面看代码才不会懵。2.1 三种连接方式对比Connector/NET、ODBC、原生 APIVB.NET 连接 MySQL 常见有三种路径工程里默认走的是 Connector/NET因为引用MySql.Data.dll最直接。三种方式的差别如下方式驱动连接字符串适用场景注意点Connector/NETMySql.Data.dllServer...;Uid...;Pwd...WinForms/WPF 常规开发需要单独安装或 NuGet 引入ODBCMySQL ODBC DriverDriver{MySQL ODBC 8.0 Driver};...老系统、Excel、第三方工具驱动位数必须和编译目标一致原生 C APIlibmysql.dll不适用于 VB.NET 直接调用C/C 项目需要手写 P/Invoke不推荐我一般会直接用 Connector/NET因为它的MySqlConnection、MySqlCommand和SqlClient的用法几乎一一对应从 SQL Server 转过来的人学习成本极低。ODBC 方式适合你不想在项目里引第三方 DLL 的场景但连接字符串的键名更啰嗦而且一旦服务器端改了认证插件ODBC 的报错信息比 Connector/NET 更隐晦。2.2 mysql_connect 的历史包袱为什么不能照抄老代码很多人在 Stack Overflow 上搜到mysql_connect(localhost, root, 123456)往 VB.NET 里一贴当然编译不过。这不是你的问题是 API 体系本身不同。PHP 的mysql_connect面向过程、全局连接、不支持预处理mysqli和 PDO 才支持参数绑定。而这个 VB.NET 工程里的写法更接近 PDO 的思想——用连接字符串创建连接对象用MySqlCommand的Parameters.AddWithValue做参数化查询。如果你打开Form1.vb看到的是这类代码Dim conn As New MySqlConnection(Serverlocalhost;Databasetest;Uidroot;Pwd123456;) Dim cmd As New MySqlCommand(SELECT * FROM users WHERE username name, conn) cmd.Parameters.AddWithValue(name, txtUsername.Text)注意这里name就是参数占位符对应 PHP 里mysqli的bind_param。为什么工程要用参数化而不是字符串拼接因为字符串拼接SELECT * FROM users WHERE username txtUsername.Text 在文本框里输入 OR 11就能绕过校验直接拖出整张用户表。这个工程既然带了登录功能就必然要面对 SQL 注入的防护问题。2.3 连接对象生命周期Open、Close 与 UsingVB.NET 里连接不是建立一次就永久有效它的生命周期直接影响程序的稳定性。常见错误是窗体加载时 Open 一次然后整个程序跑完都不关最后连接池溢出报 Too many connections。正确的做法是每次操作数据库都短开短关或者用Using块让连接对象自动释放Using conn As New MySqlConnection(connStr) conn.Open() 执行 SQL End UsingUsing语句在块结束时自动调用Dispose()内部会关闭连接并归还连接池。这比手动写conn.Close()更安全因为即使 SQL 执行抛异常Using也能保证释放。连接池归还是关键真正的 TCP 连接未必立刻断开但连接对象被标记为可复用后续 Open 会从池里拿省去握手开销。3. 连接前先把环境捋顺Connector/NET 安装、x86 编译与连接字符串参数我在拆这个工程时注意到一个细节obj目录下有x86子目录说明项目编译目标平台是 x86。这个细节很多人会忽略但它是连接 MySQL 失败的高发原因之一。如果机器上装的是 64 位 MySQL ODBC 驱动而程序编译成 x86ODBC 方式就会报 找不到数据源。所以开始写代码前环境必须要捋顺。3.1 Connector/NET 的安装与引用添加先安装 MySQL Connector/NET这样才能在 VB.NET 项目里引用MySql.Data。安装途径有两种一是去 MySQL 官网下载 MSI 安装包安装后 GAC 里会有 MySql.Data.dll二是在 Visual Studio 里用 NuGet 包管理器搜索MySql.Data直接引入这种方式对版本控制更友好。我建议用 NuGet因为可以锁定版本避免本机 GAC 版本和项目引用版本不一致导致的问题。添加引用后在代码文件顶部写Imports MySql.Data.MySqlClient如果没有这一行你写MySqlConnection时会报 类型未定义。NuGet 方式下MySql.Data.dll会复制到bin\Debug目录发布时跟着 exe 走MSI 方式则依赖 GAC部署到别的机器时如果对方没装 Connector/NET 就会启动报错。所以正式分发程序我一般把MySql.Data.dll直接放在 exe 同级目录。3.2 连接字符串参数详解Server、Port、SslMode、CharSetConnector/NET 的连接字符串键值对很多但日常项目真正需要关注的也就那几项。这个工程里的连接字符串长这样Dim connStr As String Server192.168.1.100;Port3306;Databaseuserdb;Uidroot;Pwd123456;SslModePreferred;CharSetutf8mb4;参数说明如下参数默认值作用踩坑点ServerlocalhostMySQL 主机地址连远程主机必须写 IP 或域名Port3306MySQL 服务端口改过端口必须显式写出Database无默认数据库连接后要用USE dbname时不用再写Uid / Pwd无用户名 / 密码不要在代码里写死见第 6 章SslModeNoneSSL 加密级别MySQL 8 默认开启 TLS显式设 Preferred 可避免握手失败CharSet无字符集中文乱码时设 utf8mb4SslMode这个参数在 MySQL 5.7 和 8.0 上行为不同。5.7 默认Disabled8.0 默认Preferred如果连接字符串写了SslModeNone而服务器强制 SSL会直接报 SSL connection error。反过来5.7 的老库不支持 TLS 1.2 时Preferred反而会握手失败。我自己的习惯是连本地开发库写SslModeNone连生产库写SslModePreferred两边都不卡。3.3 x86 与 AnyCPU编译器位数选择的连锁反应obj\x86说明这个工程以 x86 编译。为什么要锁 x86一种可能是项目引用了某个 32 位原生 DLL另一种是作者当时机器上只有 32 位 MySQL ODBC 驱动。如果解压后你直接改成 AnyCPU 重新编译在 64 位系统上跑Connector/NET 方式一般没问题但 ODBC 方式必踩位数坑——64 位程序连不上 32 位 ODBC 驱动会报ERROR [IM002] [Microsoft][ODBC 驱动程序管理器] 未找到数据源名称且未指定默认驱动程序解决方式就两条要么把项目编译目标改回 x86要么安装 64 位 ODBC 驱动二选一没有第三种玄学。如果你不确定自己的驱动位数可以在命令行里跑odbcad32.exe64 位和C:\Windows\SysWOW64\odbcad32.exe32 位分别查看。4. 注册登录模块拆解参数化 INSERT 与 SELECT 的落地写法MySQL_RegisterLogin.vb是这个包的核心功能文件文件名里的加号说明 Visual Studio 把它当嵌套项处理实际就是一个包含注册、登录两个功能的类或窗体。我按最常见的实现方式来拆解——注册走 INSERT登录走 SELECT两边都必须用参数化查询。4.1 注册功能哈希密码再入库用户注册的逻辑很直接检查用户名是否被占用没占用就插入新记录。但密码不能明文存。工程里如果用的是老式写法可能是直接 INSERT INTO users(username, password) VALUES( username , password )这种写法两个问题SQL 注入 密码裸奔。我按安全标准重写一遍Imports System.Security.Cryptography Public Function RegisterUser(username As String, password As String) As Boolean Dim passwordHash As String Using sha256 As New SHA256CryptoServiceProvider() Dim bytes As Byte() sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password)) passwordHash Convert.ToHexString(bytes) End Using Using conn As New MySqlConnection(connStr) conn.Open() Dim sql As String INSERT INTO users(username, password_hash, created_at) VALUES(username, passwordHash, NOW()) ON DUPLICATE KEY UPDATE username username Using cmd As New MySqlCommand(sql, conn) cmd.Parameters.AddWithValue(username, username) cmd.Parameters.AddWithValue(passwordHash, passwordHash) Return cmd.ExecuteNonQuery() 0 End Using End Using End Function这里两个细节值得说。Convert.ToHexString把 SHA256 结果转成 64 位十六进制字符串存进数据库的password_hash字段如果用 MySQL 5.7 或更早版本ON DUPLICATE KEY UPDATE需要表中存在UNIQUE索引才能生效否则重复用户名会直接抛异常而不是静默跳过。ExecuteNonQuery返回影响行数插入成功返回 1。4.2 登录校验查出一行比较哈希登录的逻辑不能是 查有没有这行而应该先按用户名查出密码哈希再与输入密码的哈希做比对。这么做的好处是区分 用户名不存在 和 密码错误 两种情况方便提示用户Public Function ValidateLogin(username As String, password As String) As Boolean Dim storedHash As String Nothing Using conn As New MySqlConnection(connStr) conn.Open() Dim sql As String SELECT password_hash FROM users WHERE username username LIMIT 1 Using cmd As New MySqlCommand(sql, conn) cmd.Parameters.AddWithValue(username, username) Dim result As Object cmd.ExecuteScalar() If result IsNot Nothing Then storedHash result.ToString() End If End Using End Using If storedHash Is Nothing Then Return False End If Using sha256 As New SHA256CryptoServiceProvider() Dim bytes As Byte() sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password)) Return Convert.ToHexString(bytes) storedHash End Using End FunctionExecuteScalar只取结果集第一行第一列比ExecuteReader少一次循环适合这种 只查一个值 的场景。注意哈希比较不能用String.Equals(storedHash, password, StringComparison.OrdinalIgnoreCase)哈希值是大小写敏感的忽略大小写会让攻击变得容易。另外真实项目里建议给密码加盐salt做法是给每个用户生成随机 salt 存库哈希时拼上 salt 再算。4.3 界面联动Form1 与登录逻辑的拼装Form1.vb一般负责界面事件比如登录按钮的 Click 事件里调ValidateLogin成功了开主窗体失败弹 MessageBox。这里有个新手常犯的问题把数据库操作直接写在按钮事件里导致界面层和数据层耦合。这个工程如果只是作业级项目这么做能跑但你要拿去扩展最好把RegisterUser和ValidateLogin单独放一个类Form1 里只保留事件处理。连接字符串的存放也是问题。Form1.vb里写connStr常量密码是明文。说实话作业和演示项目里大家都这么干能跑就行。但如果你打算部署到真实环境连接字符串必须挪到App.config并加密或者用Environment.GetEnvironmentVariable(MYSQL_CONN_STR)从环境变量读。第 6 章我会给一个封装方案。5. 连接失败排查我踩过的四个坑与对应处理这个工程相关的连接问题我拆的时候基本全踩过一遍这里挑四个最典型的按 现象 → 原因 → 解决 来记。5.1 MySQL 8.0 认证插件导致的 Authentication method caching_sha2_password现象连接字符串、用户名、密码全对但conn.Open()抛MySqlException: Authentication method caching_sha2_password not supported by any of the available plugins。原因MySQL 8.0 默认认证插件从mysql_native_password换成caching_sha2_password老版本的 Connector/NET5.x 及早期 6.x不认识这个新插件。解决两种方案我优先推荐升级 Connector/NET 到 8.0 以上因为caching_sha2_password的安全性比 native 强如果因为某些原因驱动版本不想动可以在 MySQL 里把用户认证方式改回旧格式ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;注意这个办法在 MySQL 8.4 LTS 里已被标记为 deprecated8.4 默认移除了mysql_native_password插件届时只能升级驱动没有第二条路。5.2 Host xxx is not allowed to connect to this MySQL server现象本地程序连远程 MySQL 报如上错误但同一台机器用命令行mysql -h却能连上。原因MySQL 的user表里host字段只允许localhost不允许远程 IP 访问。命令行能连是因为-h localhost走了 socket而程序连的是 TCP。解决给用户加上对应主机的授权注意生产环境不要直接开%CREATE USER app_user192.168.1.% IDENTIFIED BY StrongPass123; GRANT SELECT, INSERT, UPDATE, DELETE ON userdb.* TO app_user192.168.1.%; FLUSH PRIVILEGES;这里的192.168.1.%表示只允许这个网段访问。如果连接还是超时检查服务器防火墙 3306 端口是否开放——Windows 防火墙入站规则、云服务器安全组这两处缺一不可。5.3 Reading from the stream has failed / SSL 握手超时现象程序能连上 MySQL 5.7但换到 MySQL 8.0 后偶发Reading from the stream has failed或者干脆SSL connection error: timeout。原因MySQL 8.0 默认开启 TLS而连接字符串里SslMode没设置驱动和服务器对 SSL 握手协商不一致也可能是服务器端的 SSL 证书过期或机器时间偏差过大。解决把连接字符串里显式加上SslModePreferred;连接 5.7 时可以加SslModeNone;。如果仍然报错在服务器上检查证书有效期SHOW STATUS LIKE Ssl_server_not_after;这个值如果小于当前日期证书已过期需要在服务器配置里更新 SSL 证书并用ALTER INSTANCE RELOAD TLS重载。顺手记住客户端和服务器系统时间偏差超过一定范围也会让 TLS 握手失败NTP 校时是常被忽视的一环。5.4 Unable to connect to any of the specified MySQL hosts 且端口无响应现象连接字符串写的 Server 是localhostMySQL 装好了也能从命令行连上但程序报Unable to connect to any of the specified MySQL hosts。原因最常见的是 MySQL 服务没有监听 TCP 端口。Linux 下默认skip-networking开启时只走 socketWindows 下则要检查 MySQL 服务是否真的启动以及my.ini里的bind-address是否绑定到了非本机地址。解决先确认端口监听状态Linux 用ss -tlnp | grep 3306如果输出为空说明服务没监听 TCP去my.ini或my.cnf里检查[mysqld] port3306 bind-address0.0.0.0改完重启 MySQL 服务。Windows 下则是net start mysql报 服务无法启动这种多数是my.ini配置错误或数据目录权限不对看%PROGRAMDATA%\MySQL\MySQL Server 8.0\Data\*.err日志里有没有明确的行号错误。6. 进阶把连接封装成 DbHelper顺手解决连接池与事务工程里的连接逻辑如果散落在 Form1 和 RegisterLogin 里项目小没问题但往大了走会出现同一个窗体重重复制代码、连接字符串改一处漏一处的情况。我会把连接封装成一个DbHelper类核心只有两个方法GetConnection和ExecuteNonQuery事务单独暴露。Public NotInheritable Class DbHelper Private Shared ReadOnly _connStr As String ConfigurationManager.ConnectionStrings(MySqlConn).ConnectionString Public Shared Function GetConnection() As MySqlConnection Dim conn As New MySqlConnection(_connStr) conn.Open() Return conn End Function Public Shared Function ExecuteNonQuery(sql As String, ParamArray parameters As MySqlParameter()) As Integer Using conn As MySqlConnection GetConnection() Using cmd As New MySqlCommand(sql, conn) If parameters IsNot Nothing Then cmd.Parameters.AddRange(parameters) End If Return cmd.ExecuteNonQuery() End Using End Using End Function End Class这段代码解决了连接字符串分散的问题ConfigurationManager从App.config读连接串部署时改配置不改代码。连接池方面GetConnection每次Open都是去池里取空闲连接Using块结束Dispose后连接归还池中MySQL Connector/NET 默认启用池化Poolingtrue不需要额外配置。但有一个参数要提Connection Lifetime默认 0 表示永远不过期对长期不活跃的连接可以设置为 300 让池定期回收。事务场景需要手动控制时不要在ExecuteNonQuery里做因为事务必须跨多个命令共享同一个连接Using conn As MySqlConnection DbHelper.GetConnection() Dim tx As MySqlTransaction conn.BeginTransaction() Try Dim cmd1 As New MySqlCommand(UPDATE accounts SET balance balance - 100 WHERE id 1, conn, tx) cmd1.ExecuteNonQuery() Dim cmd2 As New MySqlCommand(UPDATE accounts SET balance balance 100 WHERE id 2, conn, tx) cmd2.ExecuteNonQuery() tx.Commit() Catch tx.Rollback() End Try End Using这里BeginTransaction返回事务对象每个MySqlCommand构造的第三个参数传入事务保证两条 UPDATE 在同一个连接里执行。如果不传事务对象第二条命令会隐式用另一个连接事务就失效了——这是我在真实项目里翻车过的地方。从那以后我每拆一个 MySQL 连接相关的工程都强制自己先做三件事查编译目标位数、确认驱动版本号、看认证插件类型。这三个变量决定了 80% 的 连接不上 问题。这个 rar 包的价值不在于里面的代码有多高级而在于它把 VB.NET MySQL 从零到登录成功这条链路完整走了一遍照着把环境配齐、把注册登录跑通你对MySqlConnection的掌握就不是背 API 而是真的能落地了。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑