關於unity專案中使用sqlite
一:準備,Mono.Data.Sqlite.dll,System.Data.dll,sqlite3.dll(X86和X86_64),這些dll檔案是必須的。將他們放到Plugins資料夾下即可。dll缺一不可,否則打包出來會有問題。然後需要將API Compatibility Level切換到.NET 2.0 。
二:在網上找了一個連線和讀取的指令碼:
using UnityEngine;
using System.Data;
using System;
using System.Collections;
using Mono.Data.Sqlite;
public class DbAccess
{
private SqliteConnection dbConnection;
private SqliteCommand dbCommand;
private SqliteDataReader reader;
public DbAccess (string connectionString)
{
OpenDB (connectionString);
}
public DbAccess ()
{
}
/// <summary>
/// 開啟資料庫
/// </summary>
/// <param name="connectionString">Connection string.</param>
public void OpenDB (string connectionString)
{
try
{
dbConnection = new SqliteConnection (connectionString);
dbConnection.Open ();
Debug.Log ("Connected to db");
}
catch(Exception e)
{
string temp1 = e.ToString();
Debug.Log(temp1);
}
}
/// <summary>
/// 關閉資料庫
/// </summary>
public void CloseSqlConnection ()
{
if (dbCommand != null) {
dbCommand.Dispose ();
}
dbCommand = null;
if (reader != null) {
reader.Dispose ();
}
reader = null;
if (dbConnection != null) {
dbConnection.Close ();
}
dbConnection = null;
Debug.Log ("Disconnected from db.");
}
/// <summary>
/// 執行sql語句
/// </summary>
/// <returns>The query.</returns>
/// <param name="sqlQuery">查詢語句.</param>
public SqliteDataReader ExecuteQuery (string sqlQuery)
{
Debug.Log ("sql="+sqlQuery);
dbCommand = dbConnection.CreateCommand ();
dbCommand.CommandText = sqlQuery;
reader = dbCommand.ExecuteReader ();
return reader;
}
/// <summary>
/// 查詢整個table的資料
/// </summary>
/// <returns>The full table.</returns>
/// <param name="tableName">表名.</param>
public SqliteDataReader ReadFullTable (string tableName)
{
string query = "SELECT * FROM " + tableName;
return ExecuteQuery (query);
}
/// <summary>
/// 插入資料
/// </summary>
/// <returns>The into.</returns>
/// <param name="tableName">表名</param>
/// <param name="values">需要插入的欄位內容,注意字串需要新增單引號 如 ‘name’</param>
public SqliteDataReader InsertInto (string tableName, string[] values)
{
string query = "INSERT INTO " + tableName + " VALUES (" + values[0];
for (int i = 1; i < values.Length; ++i) {
query += ", " + values[i];
}
query += ")";
return ExecuteQuery (query);
}
/// <summary>
/// 更新table內容
/// </summary>
/// <returns>The into.</returns>
/// <param name="tableName">Table 名稱.</param>
/// <param name="cols">需要更新的欄位名稱陣列.</param>
/// <param name="colsvalues">需要更新的欄位對應的值.</param>
/// <param name="selectkey">更新依據的欄位.</param>
/// <param name="selectvalue">更新依據欄位對應的值</param>
public SqliteDataReader UpdateInto (string tableName, string []cols,string []colsvalues,string selectkey,string selectvalue)
{
string query = "UPDATE "+tableName+" SET "+cols[0]+" = "+colsvalues[0];
for (int i = 1; i < colsvalues.Length; ++i) {
query += ", " +cols[i]+" ="+ colsvalues[i];
}
query += " WHERE "+selectkey+" = "+selectvalue+" ";
return ExecuteQuery (query);
}
/// <summary>
/// 根據刪除條件,刪除對應的資料
/// </summary>
/// <param name="tableName">Table 名稱.</param>
/// <param name="cols">欄位陣列.</param>
/// <param name="colsvalues">欄位陣列對應的值.</param>
public SqliteDataReader Delete(string tableName,string []cols,string []colsvalues)
{
string query = "DELETE FROM "+tableName + " WHERE " +cols[0] +" = " + colsvalues[0];
for (int i = 1; i < colsvalues.Length; ++i) {
query += " or " +cols[i]+" = "+ colsvalues[i];
}
return ExecuteQuery (query);
}
/// <summary>
/// 插入資料,只插入部分欄位的資料
/// </summary>
/// <returns>The into specific.</returns>
/// <param name="tableName">Table 名稱.</param>
/// <param name="cols">需要插入的欄位陣列.</param>
/// <param name="values">需要插入的欄位陣列對應的值.</param>
public SqliteDataReader InsertIntoSpecific (string tableName, string[] cols, string[] values)
{
if (cols.Length != values.Length) {
throw new SqliteException ("columns.Length != values.Length");
}
string query = "INSERT INTO " + tableName + "(" + cols[0];
for (int i = 1; i < cols.Length; ++i) {
query += ", " + cols[i];
}
query += ") VALUES (" + values[0];
for (int i = 1; i < values.Length; ++i) {
query += ", " + values[i];
}
query += ")";
return ExecuteQuery (query);
}
/// <summary>
/// 根據表名,刪除該表的全部資料
/// </summary>
/// <returns>The contents.</returns>
/// <param name="tableName">Table name.</param>
public SqliteDataReader DeleteContents (string tableName)
{
string query = "DELETE FROM " + tableName;
return ExecuteQuery (query);
}
/// <summary>
/// 建立一個數據表
/// </summary>
/// <returns>The table.</returns>
/// <param name="name">Name.</param>
/// <param name="col">Col.</param>
/// <param name="colType">Col type.</param>
public SqliteDataReader CreateTable (string name, string[] col, string[] colType)
{
if (col.Length != colType.Length) {
throw new SqliteException ("columns.Length != colType.Length");
}
string query = "CREATE TABLE " + name + " (" + col[0] + " " + colType[0];
for (int i = 1; i < col.Length; ++i) {
query += ", " + col[i] + " " + colType[i];
}
query += ")";
return ExecuteQuery (query);
}
/// <summary>
/// 根據條件篩選資料
/// </summary>
/// <returns>The where.</returns>
/// <param name="tableName">Table name.</param>
/// <param name="items">需要篩選的欄位.</param>
/// <param name="col">篩選條件的健.</param>
/// <param name="operation">篩選符號,如 >,<,= </param>.</param>
/// <param name="values">篩選條件的值.</param>
public SqliteDataReader SelectWhere (string tableName, string[] items, string[] col, string[] operation, string[] values)
{
if (col.Length != operation.Length || operation.Length != values.Length) {
throw new SqliteException ("col.Length != operation.Length != values.Length");
}
string query = "SELECT " + items[0];
for (int i = 1; i < items.Length; ++i) {
query += ", " + items[i];
}
query += " FROM " + tableName + " WHERE " + col[0] + operation[0] + "'" + values[0] + "' ";
for (int i = 1; i < col.Length; ++i) {
query += " AND " + col[i] + operation[i] + "'" + values[0] + "' ";
}
return ExecuteQuery (query);
}
}
三:然後將sqlite的資料放到了StreamingAsset檔案下,然後程式一啟動,會將資料拷到PersistentPath目錄下,防止檔案丟失。
當連線資料庫的時候,會從工程目錄下找這個檔案,如果沒有就會從沙盒路徑下拷過來,然後進去讀取。因為sqlite檔案是db結尾的,所以不能用Resources載入。 部分程式碼如下
void Awake(){
CopyFile(Application.streamingAssetsPath + dbName, Application.persistentDataPath + dbName);
}
/// <summary>
/// 拷貝檔案
/// </summary>
/// <param name="sourcePath"></param>
/// <param name="distPath"></param>
private void CopyFile(string sourcePath,string distPath) {
if (!System.IO.File.Exists(distPath)){
if (System.IO.File.Exists(sourcePath)) {
System.IO.File.Copy(sourcePath, distPath);
}
}
}
/// <summary>
/// 連線資料庫,請進行讀取資料
/// </summary>
private void ConnectSqllite() {
dbPath = getPath();
if (!System.IO.File.Exists(dbPath)) {
CopyFile(Application.persistentDataPath + dbName, dbPath);
if (!System.IO.File.Exists(dbPath)) {
JT_MessageBox.ShowMessageBox(MessageBoxStyle.OnlyOK, "提示訊息", "讀取配置檔案失敗(配置檔案丟失或損壞,請聯絡管理員)");
return;
}
db = new DbAccess("data source=" + dbPath);
}
else {
db = new DbAccess("data source=" + dbPath);
}
QueryAllData();
db.CloseSqlConnection();
}
/// <summary>
/// 讀取配置檔案,將資料存入 textConfigDic字典中
/// </summary>
public void QueryAllData() {
SqliteDataReader reader = db.ReadFullTable("systeminfo1");
int count = 0;
while (reader.Read()) {
TextConfig tc = new TextConfig();
tc.Id = int.Parse(reader["id"].ToString());
tc.Name = reader["name"].ToString();
tc.Meno = reader["meno"].ToString();
tc.VideoURL = reader["video"].ToString();
tc.SoundURL = reader["sound"].ToString();
tc.Isvideo = int.Parse(reader["isvideo"].ToString());
tc.Createdate = reader["createdate"].ToString();
textConfigDic.Add(count, tc);
//Debug.Log ("name=" + reader ["name"] + ",age=" + reader ["age"] + ",sex=" + reader ["sex"] + ",adress=" + reader ["adress"]);
count++;
}
}
/// <summary>
/// 配置檔案目錄
/// </summary>
/// <returns></returns>
string getPath() {
string path = Application.dataPath + "/" + dbName;
return path;
}
最後打包出來就OK了。
最後總結一下:主要在於dll檔案,這個花了很長時間。PC條件下,X86,X86_64兩個都要要,否則,打包出來可能會有問題。其他的基本沒什麼。
其實我個人還是喜歡Json。可能是用的多吧,輕巧方便,雖然易讀性差點。
有興趣的可以加我的個人學習交流群(小眾群,沒人說話的,哈哈):195118593
下面貼幾個講使用sqlitede 我覺得比較好的文章: