ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Unity x86下MySql.Data.dll架构不匹配排查与解决

Unity x86下MySql.Data.dll架构不匹配排查与解决 简介这是一份面向 .NET 开发者的 MySQL 8.0.13 数据访问组件包采用 x86 构建适用于桌面应用、Web 项目以及需要将 MySQL 作为数据源的各类 C# 服务端场景。资源围绕 MySql.Data 核心库并针对 EF6 与 EF Core 分别提供适配程序集可帮助解决在 .NET 环境中引用 MySQL 驱动、接入数据访问层以及离线部署时缺少官方安装包、无法直接执行安装程序等问题。压缩包为 rar 格式共 12 个文件其中 6 个 dll 提供运行时程序集5 个 xml 提供 API 注释文档1 个 installstate 记录安装状态整体仅 560KB结构紧凑便于复制到项目中引用或归档保存。已有 1423 人学习/下载适合需要手动管理依赖、定位驱动冲突或进行版本归档的 .NET 开发人员。资源中除核心数据访问主程序集外还包含 Web 适配与 Protobuf 序列化等关联依赖配套的 XML 文档可在代码编写时显示智能提示帮助开发者快速了解程序集 API减少排查引用错误的时间提升集成效率。 前阵子做了个 PC 端演示工具Unity 2021.3.32f1IL2CPP目标平台 Windows x86。逻辑不复杂客户端启动后从一个远程 MySQL 拉配置表。编译一路绿灯打包出来一运行直接抛 BadImageFormatException查了一个下午才定位到 MySql.Data.dll 8.0.13 和整个进程架构的匹配关系。后来在几个技术交流群里发现搜MySql.Data.dll x86的人真不少大多是被 Unity 老工程或者 32 位 Windows 环境卡住的。这篇就把这个 DLL 的来龙去脉、获取方式、Unity 安置姿势、运行时报错排查完整写一遍给同样在这个坑里的朋友一个可复现的解决路径。1. 一个 DLL 被冠上x86搜索词背后的项目长什么样1.1 Unity 2021.3.32 客户端直连 MySQL 的典型场景Unity 项目要连 MySQL最普遍的做法是引 Oracle 官方的 Connector/NET也就是 MySql.Data.dll。它的 API 完全对标 ADO.NETMySqlConnection、MySqlCommand、MySqlDataReader用起来和 SqlClient 几乎一样。Unity 2019 到 2021 这几代 LTS 里遇到配置下发、排行榜同步、账号验证这种需求很多项目组会在服务端之外留一个客户端直连数据库的快捷通道这时候 MySql.Data.dll 就是唯一桥梁。我遇到的情况很典型展会演示机是台老旧的 32 位 Windows 机器Unity Build Settings 里 Architecture 只能选 x86于是整个 Player 就是一个 32 位原生进程。这个进程里运行的所有托管程序集架构必须兼容 x86。很多人第一次踩坑就是忽略了这一点从 NuGet 拉一个 MySql.Data.dll 往 Assets 里一扔Editor 里跑得欢一打包就废。1.2 8.0.13 为什么成为流传最广的老版本8.0.13 是 Connector/NET 8.0 阶段一个相当稳的版本2018 年末发布同期的 MySQL 服务端也是 8.0.13。很多人其实不是主动选它而是历史遗留——网上大量 Unity 连 MySQL 的教程写于 2018 到 2019 年用的就是 8.0.11 到 8.0.13 这一段。项目从旧工程升级上来为了少折腾直接把这个 DLL 带进了新工程。这个版本好在哪它的托管依赖只有两个Google.Protobuf 和 BouncyCastle.Crypto。到了 8.0.20 之后的版本又陆续引入 System.Buffers、System.Memory 等新依赖在 Unity 的旧 API 兼容级别下更容易出幺蛾子。所以 8.0.13 在 Unity 圈子里流传广不是因为它新而是因为它够用、依赖少、教程多。1.3 先搞清楚官方 DLL 其实不区分 x86/x64这里要先纠正一个认知官方发布的 MySql.Data.dll 本体是 AnyCPU 的它本身不区分 32 位还是 64 位。真正让你需要去搜x86 版本的情况通常是下面三种目标进程本身是 32 位Unity x86 构建、老 WinForm 程序整个依赖链里某个环节位宽不对。你手里的 MySql.Data.dll 来自第三方下载站被人用 x64 平台目标重新编译过。依赖链中出现了原生库少数连接特性会用 P/Invoke 调原生组件原生库位宽和进程对不上。所以MySql.Data.dll x86这个搜索词背后真正的问题往往不是 DLL 文件本身而是进程位宽 依赖链这一整条链路。带着这个前提去排查比盲目替换 DLL 有效得多。2. 进程位宽与程序集位宽BadImageFormatException 是怎么来的2.1 两个最典型的架构不匹配信号架构不匹配最常见的两个报错一个是 BadImageFormatException一个是 FileLoadException。现象都是编译全过一运行就炸而且炸的时机很飘忽——可能在 new MySqlConnection 的时候可能在 Open() 的时候也可能在某个静态方法第一次被 JIT 的时候。这个异常的本质是 Windows 加载器的规则进程位宽和加载目标的位宽必须一致。32 位进程不能加载 PE32 格式的 64 位原生库反过来64 位进程也不能加载被标记为 32BITREQ1 的托管程序集。托管世界里 AnyCPU 算是一张豁免牌但如果程序集被明确标记成 x64-only32 位进程照样拒收。2.2 AnyCPU 在 Unity Player 里的真实表现很多人以为 AnyCPU 天下无敌其实只对了一半。.NET Framework 下AnyCPU 程序集在 64 位系统上默认以 64 位进程方式运行在 32 位系统上以 32 位方式运行。这个跟随系统的特性到了 Unity 里并不适用——Unity Player 的位宽在打包时就定了托管 DLL 只能去适配 Player而不是反过来。更要命的是AnyCPU 只能解决托管程序集这一层。Connector/NET 8.x 在某些连接特性上会通过原生层做事比如老的压缩传输协议、部分认证流程。一旦原生依赖介入位宽立刻变成硬约束。哪怕你手里的 MySql.Data.dll 是 AnyCPU只要它实际链接的原生库是 x64 的x86 Player 照样炸。这就是为什么排查的时候不能只看主 DLL得看整条依赖链。2.3 用 corflags 验证平台目标排查架构问题别靠猜用 corflags 看一眼最快。corflags 随 Visual Studio 的开发者命令行一起提供直接执行corflags.exe MySql.Data.dll官方 8.0.13 的 MySql.Data.dll输出大概是 PE32 格式、ILONLY1、32BITREQ0这才是标准的 AnyCPU。判断规则很简单PE32 32BITREQ1纯 x86 程序集只能进 32 位进程。PE32 32BITREQ0x64 程序集32 位进程加载必报 BadImageFormatException。PE32 32BITREQ0AnyCPUx86 和 x64 进程都能加载。如果你手里的 DLL 显示 PE32那基本可以确定是第三方重新编译过的 x64 版本直接换官方文件就行。这一步能在五分钟内排除掉一半的玄学报错。3. 从 Connector/NET 8.0.13 安装包里取一份干净可用的程序集3.1 下载 msi 与安装目录获取 MySql.Data.dll 唯一推荐的渠道是 MySQL 官网的 Connector/NET 安装包。找到 8.0.13 版本下载 mysql-connector-net-8.0.13.msi安装路径默认是 C:\Program Files (x86)\MySQL\MySQL Connector Net 8.0.13\。注意这里路径名里有 Program Files (x86)纯粹是因为 MySQL 安装器自己选择了 32 位安装目录和 DLL 本身的位宽没关系别被这个误导。装完后Assemblies 目录下会有几个子目录分别对应不同的 .NET 运行环境。这一步选错后面所有努力都白费。3.2 按目标框架选程序集目录子目录目标框架适用场景v4.5.2.NET Framework 4.5.2老 WinForm / WPFUnity 2018 以下v4.6.2.NET Framework 4.6.2新一点的传统 .NET 应用netstandard2.0.NET Standard 2.0Unity 2019API 兼容级别选 .NET Standard 2.0netcoreapp2.0.NET Core 2.0控制台 / 服务端程序Unity 2021.3.32 的项目如果 Project Settings Player Api Compatibility Level 选的是 .NET Standard 2.0就从 netstandard2.0 目录取如果选的是 .NET Framework 4.x就取 v4.5.2 或 v4.6.2。这个选择和 IL2CPP 的 AOT 编译有直接关系建议先确认清楚再动手。3.3 两个绑定依赖Google.Protobuf 和 BouncyCastleConnector/NET 8.0.13 有且仅有两个托管依赖必须一起拷走Google.Protobuf.dllMySql.Data 内部用 Protobuf 做 X Protocol 通信。BouncyCastle.Crypto.dll负责 caching_sha2_password 等认证加密算法。如果你只拷了一个 MySql.Data.dll 进工程编译照样能过但运行到 Open() 时大概率报 Could not load file or assembly Google.Protobuf, Version3.5.1.0...。这两个依赖同样在安装目录里或者从对应的 NuGet 包中获取。版本要和 MySql.Data 8.0.13 匹配别随手拉个最新版 Protobuf 过来程序集强名称对不上一样会炸。4. 托管 DLL 在 Unity 工程里的正确安置方式4.1 Plugins 根目录与 Inspector 平台设置网上很多教程会让你把 DLL 丢进 Assets/Plugins/x86 目录但这个目录其实是给原生插件Native Plugin用的。托管插件更稳妥的做法是放 Assets/Plugins 根目录然后在 Inspector 里逐个设置 Platform Settings。这样做的好处是平台归属清晰不会出现 Unity 打包器对子目录插件做额外处理的歧义。具体设置选中 DLLInspector 里勾选 StandaloneWindows 桌面平台CPU 一栏选 x86其他不需要的平台全部取消勾选。否则你以后打 Android 或 iOS 包时Unity 会把 Windows 的 DLL 也塞进去轻则报警告重则编译直接报错。如果你同时要发布 x64 版本就放两份x86 设置一份x64 设置一份Unity 会按构建目标自动挑选。4.2 最小可用代码与连接串参数放好 DLL 后建议先写一段最小代码验证链路别一上来就接业务逻辑using System; using MySql.Data.MySqlClient; using UnityEngine; public class MySqlSmokeTest : MonoBehaviour { void Start() { string connStr Server192.168.1.10;Port3306;Databasegame_db; Uidroot;Pwdyour_password;CharSetutf8mb4;SslModeNone;; try { using (var conn new MySqlConnection(connStr)) { conn.Open(); Debug.Log(MySQL connected, state conn.State); using (var cmd new MySqlCommand(SELECT id, name FROM player LIMIT 5, conn)) using (var reader cmd.ExecuteReader()) { while (reader.Read()) Debug.Log(reader.GetInt32(0) - reader.GetString(1)); } } } catch (Exception ex) { Debug.LogError(MySQL error: ex); } } }连接串里的 SslModeNone 是刚联调时最省事的配置内网测试往往没有配证书先保证能连上再谈加密。CharSet 推荐 utf8mb4MySQL 8.0 默认字符集就是 utf8mb4连接串不写的话遇到 emoji 或生僻字对不上很容易乱码。4.3 link.xml 防止 IL2CPP 裁剪IL2CPP 打包时会把托管程序集转成 C 再编译这个过程会做代码裁剪。裁剪器觉得没被引用的类型会被删掉而 MySql.Data 这类大量走反射加载内部类型的库很容易被误砍。典型现象是Editor 里一切正常打包后 Open() 报 FileNotFoundException 或者 MissingMethodException而且报错信息经常指向 MySqlConnection 这个入口类误导你去查连接串。解决方式是在 Assets 根目录放一个 link.xmllinker assembly fullnameMySql.Data preserveall/ assembly fullnameGoogle.Protobuf preserveall/ assembly fullnameBouncyCastle.Crypto preserveall/ /linker如果项目开了更高强度的 Managed Stripping Level三个程序集全部 preserveall 是最省心的。这是我把 8.0.13 接进 Unity 后踩的最深的一个坑花的时间比架构不匹配还多。5. 打包后最容易遇到的五个运行期错误5.1 错误一Could not load file or assembly 或其一依赖这个报错的常见原因有三个DLL 没放进 PluginsUnity 根本没打进包link.xml 缺失导致关键类型被裁剪Google.Protobuf 或 BouncyCastle 没同步。排查第一步打开打包产物目录找到 Managed 文件夹确认四个 DLLMySql.Data 加两个依赖有时还有 System 相关都在。缺哪个补哪个然后按第 4本文还有配套的精品资源点击获取
返回列表