Unity连接sqlite数据库,在windows Unity软件中成功连接,但是发布为EXE后,无法连接
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity连接sqlite数据库,在windows Unity软件中成功连接,但是发布为EXE后,无法连接相关的知识,希望对你有一定的参考价值。
我使用Unity连接sqlite,在windows Unity 5.1.0f3 (64-bit)下连接正常。但是把该项目发布为EXE后,无法就连接sqlite啦。很奇怪。
我把Unity工程包附上:http://pan.baidu.com/s/1gd71OnL。请大神帮我解答一下,纠结半个月啦。
在开发环境下一切正常
发布为EXE后,sqlite连接不成功。我经过调试发现:连 File.Exists(path)这个函数也不能被调用
选择开始菜单中→程序→【Management SQL Server 2008】→【SQL Server Management Studio】命令,打开【SQL Server Management Studio】窗口,并使用Windows或 SQL Server身份验证建立连接。
在【对象资源管理器】窗口中展开服务器,然后选择【数据库】节点
右键单击【数据库】节点,从弹出来的快捷菜单中选择【新建数据库】命令。
执行上述操作后,会弹出【新建数据库】对话框。在对话框、左侧有3个选项,分别是【常规】、【选项】和【文件组】。完成这三个选项中的设置会后,就完成了数据库的创建工作,
在【数据库名称】文本框中输入要新建数据库的名称。例如,这里以“新建的数据库”。
在【所有者】文本框中输入新建数据库的所有者,如sa。根据数据库的使用情况,选择启用或者禁用【使用全文索引】复选框。
在【数据库文件】列表中包括两行,一行是数据库文件,而另一行是日记文件。通过单击下面的【添加】、【删除】按钮添加或删除数据库文件。
切换到【选项页】、在这里可以设置数据库的排序规则、恢复模式、兼容级别和其他属性。
切换到【文件组】页,在这里可以添加或删除文件组。
完成以上操作后,单击【确定】按钮关闭【新建数据库】对话框。至此“新建的数据”数据库创建成功。新建的数据库可以再【对象资源管理器】窗口看到。 参考技术A 这个问题我也遇到了,我是这样解决的。先介绍环境:我是在windows7上运行Unity5.6.6,数据库也是sqlite,最终发布成EXE文件,也是在PC上运行。
发布前,我的数据库文件db放在unity的Asset目录下。
(1)象网上许多友友介绍的一样,先在C:\Program Files\Unity 5.6.6f2(64-bit)\Editor\Data\Mono\lib\mono\2.0目录下,把:Mono.Data.Sqlite.dll、sqlite3.dll、System.Data.dll这三个文件复制到你的工程文件Asset\Plugins\目录中。
然后直接发布,比如发布后的文件分别有两项:ex.EXE,ex_Data(这是目录)。
(2)此时,你把工程文件Asset\的数据库文件db,复制到发布后的ex_Data\目录下就可以了。我试过了四、五次,都没出现问题。
但愿你能成功!!!
为 Unity 设置数据库 (SQLite)
【中文标题】为 Unity 设置数据库 (SQLite)【英文标题】:Setup Database (SQLite) for Unity 【发布时间】:2018-11-18 02:20:10 【问题描述】:我查看了太多教程,无法列出,它们都推荐相同的东西。但是,他们并没有帮助解决我的问题。
我试图在我的项目中包含一个 SQLite DB,并且在为 PC、MAC 和 Linux Standalone 构建(在 Windows 机器上测试)时,该数据库按预期工作。在 Android 设备上进行测试时,出现以下错误。
E/Unity: ArgumentException: Invalid ConnectionString format for parameter "/storage/emulated/0/Android/data/com.tbltools.tbl_project/files/TBLDatabase.db"
at Mono.Data.Sqlite.SqliteConnection.ParseConnectionString (System.String connectionString) [0x00000] in <filename unknown>:0
at Mono.Data.Sqlite.SqliteConnection.Open () [0x00000] in <filename unknown>:0
at UIHandler+<RequestAllStudentNames>c__Iterator2.MoveNext () [0x00000] in <filename unknown>:0
at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) [0x00000] in <filename unknown>:0
我认为对 connectionString 进行修改应该很简单,但这并没有解决我的问题。这是我目前所拥有的:
if (Application.platform != RuntimePlatform.Android)
// The name of the db.
tblDatabase = "URI=file:" + Application.dataPath + "/TBLDatabase.db"; //returns the complete path to database file exist.
else
tblDatabase = Application.persistentDataPath + "/TBLDatabase.db";
if (!File.Exists(tblDatabase))
// if it doesn't ->
Debug.LogWarning("File \"" + tblDatabase + "\" does not exist. Attempting to create from \"" + Application.dataPath + "!/assets/" + "TBLDatabase.db");
// open StreamingAssets directory and load the db ->
// #if UNITY_ANDROID
var loadDb = new WWW("jar:file://" + Application.dataPath + "!/assets/" + "TBLDatabase.db"); // this is the path to your StreamingAssets in android
while (!loadDb.isDone) // CAREFUL here, for safety reasons you shouldn't let this while loop unattended, place a timer and error check
// then save to Application.persistentDataPath
File.WriteAllBytes(tblDatabase, loadDb.bytes);
//open db connection
var connection = new SqliteConnection(tblDatabase);
connection.Open();
var command = connection.CreateCommand();
我使用了 adb shell 并从我的 Android 设备中提取了数据库,一切都符合预期(数据库确实存在并且它不是空的)。
我相信我拥有所有相关的 dll 文件,但如果有人能给我一些指导,我将不胜感激。
**************************************************** ****编辑********************************************* *
此后,我根据给出的建议进行了以下更改。
我现在正在调用以下方法来启动我的连接并处理数据库请求StartCoroutine(RunDbCode(dbFileName, jsonStudentID, jsonIndiNames, jsonIndiStudentNumbers));
那我有以下方法:
IEnumerator RunDbCode(string fileName, List jsonStudentID, List jsonIndiNames, List jsonIndiStudentNumbers)
//Where to copy the db to
string dbDestination = Path.Combine(Application.persistentDataPath, "data");
dbDestination = Path.Combine(dbDestination, fileName);
//Check if the File do not exist then copy it
if (!File.Exists(dbDestination))
//Where the db file is at
string dbStreamingAsset = Path.Combine(Application.streamingAssetsPath, fileName);
byte[] result;
//Read the File from streamingAssets. Use WWW for Android
if (dbStreamingAsset.Contains("://") || dbStreamingAsset.Contains(":///"))
WWW www = new WWW(dbStreamingAsset);
yield return www;
result = www.bytes;
else
result = File.ReadAllBytes(dbStreamingAsset);
Debug.Log("Loaded db file");
//Create Directory if it does not exist
if (!Directory.Exists(Path.GetDirectoryName(dbDestination)))
Directory.CreateDirectory(Path.GetDirectoryName(dbDestination));
//Copy the data to the persistentDataPath where the database API can freely access the file
File.WriteAllBytes(dbDestination, result);
Debug.Log("Copied db file");
//Now you can do the database operation
//open db connection
var connection = new SqliteConnection(dbDestination);
connection.Open();
var command = connection.CreateCommand();
// Drop the table if it already exists.
command.CommandText = "DROP TABLE IF EXISTS existing_individual;";
command.ExecuteNonQuery();
var sql = "CREATE TABLE existing_individual (studentID VARCHAR(23), fullName VARCHAR(50), studentNumber VARCHAR(20))";
command.CommandText = sql;
command.ExecuteNonQuery();
//Inserting the exisiting student names returned, into the SQLite DB
int count = 0;
foreach (var individuals in jsonStudentID)
//looping through the existing students registered for the individual quiz - below has been written to avoid SQL injection
sql = "INSERT INTO existing_individual (studentID, fullName, studentNumber) VALUES (@jsonStudentID, @jsonIndiNames, @jsonIndiStudentNumbers)";
command.Parameters.AddWithValue("@jsonStudentID", jsonStudentID[count]);
command.Parameters.AddWithValue("@jsonIndiNames", jsonIndiNames[count]);
command.Parameters.AddWithValue("@jsonIndiStudentNumbers", jsonIndiStudentNumbers[count]);
command.CommandText = sql;
command.ExecuteNonQuery();
count++;
//close the connection
command.Dispose();
command = null;
connection.Close();
connection = null;
但是,我仍然收到以下错误:
06-08 15:26:56.498 16300-16315/? E/Unity: ArgumentException: Invalid ConnectionString format for parameter "/storage/emulated/0/Android/data/com.tbltools.tbl_project/files/data/TBLDatabase.db"
at Mono.Data.Sqlite.SqliteConnection.ParseConnectionString (System.String connectionString) [0x00000] in <filename unknown>:0
at Mono.Data.Sqlite.SqliteConnection.Open () [0x00000] in <filename unknown>:0
at UIHandler+<RunDbCode>c__Iterator3.MoveNext () [0x00000] in <filename unknown>:0
at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) [0x00000] in <filename unknown>:0
UnityEngine.MonoBehaviour:StartCoroutineManaged2(IEnumerator)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
<RequestAllStudentNames>c__Iterator2:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
(Filename: Line: -1)
06-08 15:26:56.502 16300-16315/? E/Unity: ArgumentException: Invalid ConnectionString format for parameter "URI"
at Mono.Data.Sqlite.SqliteConnection.ParseConnectionString (System.String connectionString) [0x00000] in <filename unknown>:0
at Mono.Data.Sqlite.SqliteConnection.Open () [0x00000] in <filename unknown>:0
at UIHandler.CreateIndiButton () [0x00000] in <filename unknown>:0
at UIHandler+<RequestAllStudentNames>c__Iterator2.MoveNext () [0x00000] in <filename unknown>:0
at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) [0x00000] in <filename unknown>:0
我还将我的数据库添加到“StreamingAssets”文件夹中,如下图所示:
下面还显示了包含我的 dll 文件的插件文件夹的图像。
【问题讨论】:
你把数据库文件放在你项目的什么地方了? @Programmer 我尝试将数据库文件存储在 assets 文件夹中,并在 assets 文件夹中创建 StreamingAssets 文件夹并将副本也存储在其中。然而,这并没有帮助。 嗨@Programmer! - chat.***.com/rooms/info/172973 ? 【参考方案1】:有关此主题的大多数教程都已过时。
查看了代码并发现了一些问题,但我不知道这些是否是您收到此错误的原因。 WWW
应该在协程函数中使用,以便您可以通过在 while
循环中添加 yield return null
来让出或等待 loadDb.isDone
完成。您也可以生成 WWW
请求本身,这就是我将在回答中使用的方法。
另外,jar:file://" + Application.dataPath
是旧代码。为此使用Application.streamingAssetsPath
。此外,您不需要"URI=file:" + Application.dataPath
。只需为此使用Application.persistentDataPath
。
我只是说明如何进行设置。
设置 MANAGED 代码部分:
1.转到您的 Unity 安装路径
<UnityInstallationDirecory>\Editor\Data\Mono\lib\mono\2.0
复制以下文件:
I18N.MidEast.dll
I18N.Other.dll
I18N.Rare.dll
I18N.West.dll
Mono.Data.Sqlite.dll
Mono.Data.SqliteClient.dll
System.Data.dll
到项目的<ProjectName>\Assets\Plugins
路径。
这将允许您从 Mono.Data.Sqlite
命名空间编译 API 而不会出现任何错误。
设置 UNMANAGED 代码部分:
在此步骤中,您将需要获取本机 Sqlite 库。你可以得到source code,构建它并使用它或者使用已经预编译的binray。
1.获取 Windows
的本机库从here下载预编译好的Windows 64位sqlite3.dll
,放到<ProjectName>\Assets\Plugins\x86_64
路径下。
如果使用 Windows 32 位,则从 here 获取 sqlite3.dll
版本并将其放入 <ProjectName>\Assets\Plugins\x86
路径中。
2.获取Android
的原生库从 Android ARM 处理器下载预编译的libsqlite3.so
here 并将其放在<ProjectName>\Assets\Plugins\Android\libs\armeabi-v7a
路径中。
从Android Intel x86 处理器下载预编译的libsqlite3.so
here 并将其放在<ProjectName>\Assets\Plugins\Android\libs\x86
路径中。
这涵盖了大多数在 Android 设备上使用的processors。
3.获取UWP
的本机库A。下载 WSA 文件夹,然后将 WSA 文件夹放入 <ProjectName>\Assets\Plugins
路径。该文件夹包含本机部分。
B。在 <ProjectName>\Assets
路径中创建 2 个名为 "mcs.rsp" 和 "csc.rsp" 的文件。 p>
C。在 "mcs.rsp" 和 "csc.rsp" 文件中添加以下内容:
-r:I18N.MidEast.dll
-r:I18N.Other.dll
-r:I18N.Rare.dll
-r:I18N.West.dll
-r:Mono.Data.Sqlite.dll
-r:Mono.Data.SqliteClient.dll
-r:System.Data.dll
D。为 UWP 构建时,您必须将托管 dll 移动到项目的 root 文件夹。因此,将I18N.MidEast.dll
、I18N.Other.dll
、I18N.Rare.dll
、I18N.West.dll
、Mono.Data.Sqlite.dll
、Mono.Data.SqliteClient.dll
、System.Data.dll
移动到 <ProjectName>
路径 not <ProjectName>\Assets\Plugins
路径。
4。对于 iOS、Linux 和 Mac,您似乎无需为它们下载任何其他内容或执行此步骤。它们通常内置原生预编译的 Sqlite 库。
在构建中包含数据库文件:
1。在您的<ProjectName>\Assets
文件夹中创建一个文件夹并将其命名为StreamingAssets。拼写很重要,并且区分大小写。
2。将数据库文件 (TBLDatabase.db
) 放入此 StreamingAssets 文件夹中。
在构建项目后访问数据库文件
Sqlite 无法处理构建中 StreamingAssets 文件夹中的文件,因为这是只读路径。此外,Android 要求您使用 WWW
API 而不是标准的 System.IO
API 从 StreamingAssets 文件夹中读取数据。您必须将 db 文件从 Application.streamingAssetsPath/filename.db
复制到 Application.persistentDataPath/filename.db
。
在某些平台上,您需要在Application.persistentDataPath
内创建一个文件夹并将数据保存到该文件夹中。总是这样做。下面示例代码中的文件夹是“data”,因此将变为Application.persistentDataPath/data/filename.db
。
3.由于上面的语句,检查数据库文件是否存在于
Application.persistentDataPath/data/filename.db
。如果是,请使用Application.persistentDataPath/data/filename.db
作为数据库操作的路径。如果没有,请从 #4 继续。
4.读取StreamingAssets文件夹中的数据库文件并将其复制到Application.persistentDataPath
在某些平台上,您需要在Application.persistentDataPath
中创建一个文件夹并将数据保存到该文件夹中。总是这样做。下例中的文件夹为“data”。
检测这是否是Android并使用WWW
从Application.streamingAssetsPath/filename.db
读取文件。使用 File.ReadAllBytes
在 Android 以外的任何其他设备上阅读它。在您的示例中,您为此使用了Application.platform
。在我的示例中,我将简单地检查路径是否包含 "://"
或 :///
来执行此操作。
5。读取文件后,将刚刚读取的数据写入Application.persistentDataPath/data/filename.db
和File.WriteAllBytes
。现在,您可以使用此路径进行数据库操作。
6.前缀 "URI=file:"
到 Application.persistentDataPath/data/filename.db
路径,这是在使用 Sqlite API 进行数据库操作时应该使用的路径。
理解所有这些非常重要,以便在发生变化时修复它,但我已经完成了下面的步骤 #3 到 #6。
IEnumerator RunDbCode(string fileName)
//Where to copy the db to
string dbDestination = Path.Combine(Application.persistentDataPath, "data");
dbDestination = Path.Combine(dbDestination, fileName);
//Check if the File do not exist then copy it
if (!File.Exists(dbDestination))
//Where the db file is at
string dbStreamingAsset = Path.Combine(Application.streamingAssetsPath, fileName);
byte[] result;
//Read the File from streamingAssets. Use WWW for Android
if (dbStreamingAsset.Contains("://") || dbStreamingAsset.Contains(":///"))
WWW www = new WWW(dbStreamingAsset);
yield return www;
result = www.bytes;
else
result = File.ReadAllBytes(dbStreamingAsset);
Debug.Log("Loaded db file");
//Create Directory if it does not exist
if (!Directory.Exists(Path.GetDirectoryName(dbDestination)))
Directory.CreateDirectory(Path.GetDirectoryName(dbDestination));
//Copy the data to the persistentDataPath where the database API can freely access the file
File.WriteAllBytes(dbDestination, result);
Debug.Log("Copied db file");
try
//Tell the db final location for debugging
Debug.Log("DB Path: " + dbDestination.Replace("/", "\\"));
//Add "URI=file:" to the front of the url beore using it with the Sqlite API
dbDestination = "URI=file:" + dbDestination;
//Now you can do the database operation below
//open db connection
var connection = new SqliteConnection(dbDestination);
connection.Open();
var command = connection.CreateCommand();
Debug.Log("Success!");
catch (Exception e)
Debug.Log("Failed: " + e.Message);
用法:
string dbFileName = "TBLDatabase.db";
void Start()
StartCoroutine(RunDbCode(dbFileName));
【讨论】:
我建议删除你当前的插件 sqlite 和文件夹。删除文件夹,然后重新开始。请注意,如果您不关闭 Unity,这可能不起作用,因为 Unity 会用已经加载的旧 dll 覆盖您的新 dll。 非常感谢您在过去几天一直陪伴我解决这个问题。我刚刚测试过,它现在可以在所有平台上运行。如果可以,我会请你喝啤酒! @Displayname 欢迎您。我还尝试添加 WebGL 支持,因为在任何地方都没有视觉上的支持,但是在编译 c 源代码后它不起作用。没有时间继续试验,但如果我有时间再次使用 WebGL,我会再次更新。 好吧,我认为您所做的工作是一个很棒的文档,许多其他人将来会从中受益。再次感谢,我会尽量让你一个人呆一会儿! 没有被打扰,是的,其他人会从中受益。编码愉快。【参考方案2】:当我们尝试在 Unity 2019 或更高版本中使用 SQLite 时会出现此错误。由于缺少 Unity 2019 或更高版本的 Mono 库而发生此错误。如果您使用的是 Unity 2018 或更低版本,则不会出现此错误。
如果您安装了 Unity 2018 或以下版本,请转到安装目录<UnityInstallationDirecory>\Editor\Data\Mono\lib\mono\2.0
并复制以下文件:
I18N.MidEast.dll
I18N.Other.dll
I18N.Rare.dll
I18N.West.dll
Mono.Data.Sqlite.dll
Mono.Data.SqliteClient.dll
System.Data.dll
到项目的<ProjectName>\Assets\Plugins
路径。
或者您可以通过将 Unity 版本降级到 2018 或更低版本来解决此错误。
【讨论】:
以上是关于Unity连接sqlite数据库,在windows Unity软件中成功连接,但是发布为EXE后,无法连接的主要内容,如果未能解决你的问题,请参考以下文章