找回密碼
 注冊帳號

掃一掃,訪問微社區

zhang273162308 Unity實用小工具或腳本—以對象形式操作Sqlite數據庫(一)

64
回復
1980
查看
打印 上一主題 下一主題
[ 復制鏈接 ]
排名
141
昨日變化

125

主題

596

帖子

7068

積分

Rank: 9Rank: 9Rank: 9

UID
3579
好友
110
蠻牛幣
5900
威望
0
注冊時間
2013-9-10
在線時間
1614 小時
最后登錄
2020-4-11

專欄作家活力之星游戲蠻牛QQ群會員蠻牛哥

馬上注冊,結交更多好友,享用更多功能,讓你輕松玩轉社區。

您需要 登錄 才可以下載或查看,沒有帳號?注冊帳號

x
本帖最后由 zhang273162308 于 2019-11-29 14:46 編輯
一、前言
       本文主要介紹在Unity中怎么使用輕量級數據庫Sqlite,并利用反射將C#定義的數據類直接映射到數據庫的表中,類似于安卓的"DataSupport"類,可以直接按照如下操作保存數據到數據庫:
[AppleScript] 純文本查看 復制代碼
//定義一個類Book
public class Book extends DataSupport {
    ...
}
//添加數據到表中
Book book = new Book();
                book.setName("The Da Vinci Code");
                book.setAuthor("Dan Brown");
                book.setPages(454);
                book.setPrice(16.96);
                book.setPress("Unknow");
                book.save();

而不用在直接操作Sql語句插入數據到數據庫,如:
[C#] 純文本查看 復制代碼
INSERT INTO TABLE_NAME [(column1, column2, column3,...columnN)]  
VALUES (value1, value2, value3,...valueN);

實現數據庫的面向對象操作,而不是再在使用過程中直接面對繁瑣的Sql語句,避免輸入錯誤帶來數據操作錯誤的問題,而且也非常容易維護。
二、實現
1、配置環境
   我使用的是在Windows下的Unity2018.4.2,配置參考宣雨松-研究院之使用C#語言建立本地數據庫 + Sqlite + Unity3D 踩過的那些坑 & 全流程簡介。我也是按照這兩篇文章進行配置的,具體過程我也再詳細介紹一下。
1.1、首先,在Unity的安裝目錄中找到Mono.Data.Sqlite.dll 文件 與System.Data.dll文件,如果找不到可以去雨松的文章自行下載,如圖所示:
?
?

1.2、然后在Unity的Asset目錄下建一個Plugins文件夾,然后將剛剛找到的兩個Mono.Data.Sqlite.dll 文件 與System.Data.dll文件拖到這個文件夾下,如圖所示:

導入之后出現如下錯誤:這個意思是有導入的dll文件不適合當前Unity設置的.Net版本。

選中System.Data文件,修改它為如圖所示:

下載sqlite3文件sqlite3.dll下載地址,選擇適合PC平臺電腦系統位數的文件,我選擇下載的文件如圖所示:

并將下載好的文件也托人到unity的Plugin文件下,該文件導入之后不需要進行配置修改。
1.3、最后在PlayerSetting里的設置如圖所示:

2、Sql數據庫操作代碼
2.1、我將雨松的代碼進行了一些修改,也建立了一個操作Sql語句命令的工具類,代碼如下:主要是創建數據庫,后續會加上更加豐富的功能。
[C#] 純文本查看 復制代碼
using Mono.Data.Sqlite;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

namespace Sql.DbMapping
{
    /// <summary>
    /// 數據庫命令執行控制類
    /// </summary>
    public class SqlDbCommandCtr 
    {
        #region 變量

        private SqliteConnection sqlConnect;
        private SqliteCommand sqlCommand;
        private SqliteDataReader sqlReader;

        #endregion

        #region 公有方法

        public SqlDbCommandCtr(string dataBaseUrl,string dbName)
        {
            Open(dataBaseUrl,dbName);
        }

        /// <summary>
        /// 根據路徑打開數據庫,如果沒有就創建數據庫
        /// </summary>
        /// <param name="dbURL"></param>
        public void Open(string dbURL,string dbName)
        {
            if(!File.Exists(dbURL))
            {
                Directory.CreateDirectory(dbURL);
            }
            string tempStr = "URI=file:" + dbURL + "/" + dbName;
            try
            {
                sqlConnect = new SqliteConnection(tempStr);
                sqlConnect.Open();
                Debug.Log("Connected to db");
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
        }
        /// <summary>
        /// 關閉數據庫的連接
        /// </summary>
        public void Close()
        {
            if (sqlCommand != null)
            {
                sqlCommand.Dispose();
            }
            sqlCommand = null;
            if (sqlReader != null)
            {
                sqlReader.Dispose();
            }
            sqlReader = null;
            if (sqlConnect != null)
            {
                sqlConnect.Close();
            }
            sqlConnect = null;
            Debug.Log("Disconnected from db.");
        }
        /// <summary>
        /// 執行Sql語句命令,并且返回命令行的讀取
        /// </summary>
        /// <param name="textSqlCmd">sql語句命令文本</param>
        /// <returns></returns>
        public SqliteDataReader ExeCommand(string textSqlCmd)
        {
            sqlCommand = sqlConnect.CreateCommand();
            sqlCommand.CommandText = textSqlCmd;
            sqlReader = sqlCommand.ExecuteReader();
            return sqlReader;
        }
        /// <summary>
        /// 創建表,如果表不存在則創建新的,如果存在就不創建
        /// </summary>
        /// <param name="tableName">表名稱</param>
        /// <param name="listDbField">表字段列表</param>
        /// <returns></returns>
        public SqliteDataReader CreateTable(string tableName, List<DB_Field> listDbField)
        {
            if (null == listDbField || 0 == listDbField.Count)
            {
                throw new SqliteException("創建的表字段為空!");
            }
            string tempCmd = "CREATE TABLE IF NOT exists " + tableName + "(" + listDbField[0].Name + " " + listDbField[0].Type;
            for (int i = 1; i < listDbField.Count; i++)
            {
                tempCmd += ", " + listDbField[i].Name + " " + listDbField[i].Type;
            }
            tempCmd += ")";
            return ExeCommand(tempCmd);
        }
        /// <summary>
        /// 讀取整個表
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public SqliteDataReader ReadTable(string tableName)
        {
            string tempCmd = "SELECT * FROM " + tableName;
            return ExeCommand(tempCmd);
        }

        /// <summary>
        /// 插入數據
        /// </summary>
        /// <param name="tableName">表名字</param>
        /// <param name="listDbField">字段列表</param>
        /// <returns></returns>
        public SqliteDataReader InsertData(string tableName, List<DB_Field> listDbField)
        {
            if (null == listDbField || 0 == listDbField.Count)
            {
                throw new SqliteException("字段列表內容為空!");
            }
            string tempCmd = "INSERT INTO " + tableName + " ";
            string tempCmdFields = listDbField[0].Name;
            string tempCmdValues = listDbField[0].Value;
            for (int i = 1; i < listDbField.Count; i++)
            {
                tempCmdFields += "," + listDbField[i].Name;
                tempCmdValues += "," + listDbField[i].Value;
            }
            tempCmd += " (" + tempCmdFields + ") " + "VALUES (" + tempCmdValues + ")";
            //  Debug.Log(tempCmd);
            return ExeCommand(tempCmd);
        }
        /// <summary>
        /// 刪除滿足條件的數據
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="isOr">條件是或還是且</param>
        /// <param name="listDbField">條件字段列表,動態參數</param>
        /// <returns></returns>
        public SqliteDataReader DeleteData(string tableName, bool isOr = true, params DB_Field[] listDbField)
        {
            if (null == listDbField || 0 == listDbField.Length)
            {
                throw new SqliteException("字段列表內容為空!");
            }
            string tempCmd = "DELETE FROM " + tableName + " WHERE " + listDbField[0].Name + " = " + listDbField[0].Value;
            string tempIsOr = isOr ? " or " : " and ";
            for (int i = 1; i < listDbField.Length; ++i)
            {
                tempCmd += tempIsOr + listDbField[i].Name + " = " + listDbField[i].Value;
            }

            //Debug.Log(tempCmd);

            return ExeCommand(tempCmd);
        }


        #endregion

    }
}


2.2、將普通類映射到數據庫表
這一步是本文的重點操作,定義一個自定義屬性映射類AttrMappingClass2DbTable,代碼如下:該用來將后續我們自己定義的數據類進行屬性標注,將自定數據類的屬性或字段類型和數據庫進行映射
游客,如果您要查看本帖隱藏內容請回復


2.3、整個項目中用到的公共自定義數據類型代碼為:
[AppleScript] 純文本查看 復制代碼
 /// <summary>
/// 自定義類到數據庫表的屬性映射類
/// </summary>

[AttributeUsage(AttributeTargets.Property, Inherited = true)]
public class AttrMappingClass2DbTable : Attribute
{
/// <summary>
/// 類的該成員映射對應數據庫表字段的類型。
/// </summary>
public string M_FieldType
{
get; private set;
}

/// <summary>
/// 類的該成員映射對應數據庫表字段的默認值
/// </summary>
public object M_DefaultValue
{
get; private set;
}
/// <summary>
/// 
/// </summary>
/// <param name="strFieldName">類的該成員映射的數據庫對應表字段名稱。</param>
/// <param name="fielType">類的該成員映射對應數據庫表字段的類型。</param>
/// <param name="defaultValue">類的該成員映射對應數據庫表字段的默認值</param>
public AttrMappingClass2DbTable(string fielType, object defaultValue = null)
{
M_FieldType = fielType;
M_DefaultValue = defaultValue;
}
}


2.4、最后定義一個測試的類,繼承基類DataClass2DbTable,然后在測試腳本中進行數據庫操作,代碼如下:
游客,如果您要查看本帖隱藏內容請回復

可以看見,此處對數據進行插入操作已經非常簡單了,只需要頂一個基類DataClass2DbTable派生類的對象,然后對其賦值,最后調動插入數據的方法就可以。打開數據庫查看結果如圖所示:我這里故意將數據按照雨松寫的文章里面安排的放在這個文件夾目錄下,其實可以放在任何文件夾,只要修改數據庫的路徑就可以。

從圖中可以看到我們已經將數據插入進去了
三、總結
1、詳細介紹了在unity中使用Sqliite數據庫的過程和注意事項,最重要的是需要三個dll文件的導入和配置
2、改進了原來在C#里面操作Sql語句和數據進行連接并操作數據庫進行增、刪、改、查的操作,增加了從類直接到數據庫表的數據映射操作,之后可以直接對類進行操作,由類管理和數據庫底層Sql語句的代碼,大大的簡化了數據庫操作的開發流程。
3、后續還會對數據庫進行更加完善的操作,包括刪除、更新和查找等
4、unity工程下載:
游客,如果您要查看本帖隱藏內容請回復

回復

使用道具 舉報

6蠻牛粉絲
1408/1500
排名
1960
昨日變化

2

主題

322

帖子

1408

積分

Rank: 6Rank: 6Rank: 6

UID
147717
好友
0
蠻牛幣
2140
威望
0
注冊時間
2016-5-5
在線時間
394 小時
最后登錄
2020-3-30
沙發
2019-11-29 15:37:29 只看該作者
學習了  感謝分享

點評

是的  發表于 2019-12-14 21:14
回復 支持 1 反對 0

使用道具 舉報

6蠻牛粉絲
1067/1500
排名
3929
昨日變化

0

主題

330

帖子

1067

積分

Rank: 6Rank: 6Rank: 6

UID
251353
好友
0
蠻牛幣
7737
威望
0
注冊時間
2017-10-29
在線時間
357 小時
最后登錄
2020-4-3
板凳
2019-11-29 16:01:27 只看該作者
謝謝大佬
回復

使用道具 舉報

4四處流浪
356/500
排名
5211
昨日變化

0

主題

44

帖子

356

積分

Rank: 4

UID
114753
好友
0
蠻牛幣
457
威望
0
注冊時間
2015-7-22
在線時間
36 小時
最后登錄
2019-11-30
地板
2019-11-30 09:17:56 只看該作者
感謝感謝感謝感謝感謝!支持!!
回復 支持 反對

使用道具 舉報

4四處流浪
356/500
排名
5211
昨日變化

0

主題

44

帖子

356

積分

Rank: 4

UID
114753
好友
0
蠻牛幣
457
威望
0
注冊時間
2015-7-22
在線時間
36 小時
最后登錄
2019-11-30
5#
2019-11-30 09:19:21 只看該作者
感謝感謝感謝感謝感謝!支持!!支持!!
回復 支持 反對

使用道具 舉報

4四處流浪
316/500
排名
20608
昨日變化

6

主題

140

帖子

316

積分

Rank: 4

UID
143117
好友
0
蠻牛幣
99
威望
0
注冊時間
2016-3-23
在線時間
140 小時
最后登錄
2020-1-18
6#
2019-11-30 15:35:18 只看該作者
66666666666學習學習學習
回復 支持 反對

使用道具 舉報

5熟悉之中
630/1000
排名
6777
昨日變化

15

主題

97

帖子

630

積分

Rank: 5Rank: 5

UID
265691
好友
1
蠻牛幣
5002
威望
0
注冊時間
2018-1-22
在線時間
312 小時
最后登錄
2020-3-10
7#
2019-12-2 08:29:38 只看該作者
謝謝大佬分享知識
回復 支持 反對

使用道具 舉報

7日久生情
4416/5000
排名
62
昨日變化

0

主題

344

帖子

4416

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
61610
好友
0
蠻牛幣
4952
威望
0
注冊時間
2014-12-16
在線時間
1271 小時
最后登錄
2020-4-16
8#
2019-12-2 08:36:47 只看該作者
hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu hui hu
回復 支持 反對

使用道具 舉報

7日久生情
2444/5000
排名
1621
昨日變化

0

主題

776

帖子

2444

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
148286
好友
0
蠻牛幣
4427
威望
0
注冊時間
2016-5-11
在線時間
868 小時
最后登錄
2020-4-17
9#
2019-12-2 09:26:17 只看該作者
回復

使用道具 舉報

7日久生情
1935/5000
排名
2307
昨日變化

7

主題

406

帖子

1935

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
175097
好友
6
蠻牛幣
2857
威望
0
注冊時間
2016-10-12
在線時間
898 小時
最后登錄
2020-4-17
10#
2019-12-2 09:28:49 只看該作者
學習~~~~~~~~~
回復 支持 反對

使用道具 舉報

7日久生情
1935/5000
排名
2307
昨日變化

7

主題

406

帖子

1935

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
175097
好友
6
蠻牛幣
2857
威望
0
注冊時間
2016-10-12
在線時間
898 小時
最后登錄
2020-4-17
11#
2019-12-2 09:31:07 只看該作者
學習~~~~~~~~~~~~~~~~~~~~~~~~~~~
回復 支持 反對

使用道具 舉報

6蠻牛粉絲
1033/1500
排名
3990
昨日變化

2

主題

157

帖子

1033

積分

Rank: 6Rank: 6Rank: 6

UID
246321
好友
0
蠻牛幣
7443
威望
0
注冊時間
2017-9-27
在線時間
500 小時
最后登錄
2020-4-7
12#
2019-12-2 09:37:26 只看該作者
學習了  感謝分享
回復 支持 反對

使用道具 舉報

0

主題

43

帖子

55

積分

Rank: 2Rank: 2

UID
335753
好友
0
蠻牛幣
72
威望
0
注冊時間
2019-11-12
在線時間
12 小時
最后登錄
2019-12-19
13#
2019-12-2 19:01:27 只看該作者
看不懂 不過看起來很專業
回復 支持 反對

使用道具 舉報

排名
64940
昨日變化

0

主題

11

帖子

16

積分

Rank: 1

UID
169072
好友
0
蠻牛幣
22
威望
0
注冊時間
2016-9-18
在線時間
3 小時
最后登錄
2019-12-4
14#
2019-12-4 16:01:39 只看該作者
學習了  感謝分享
回復 支持 反對

使用道具 舉報

5熟悉之中
598/1000
排名
9113
昨日變化

3

主題

131

帖子

598

積分

Rank: 5Rank: 5

UID
60012
好友
0
蠻牛幣
5153
威望
0
注冊時間
2014-12-8
在線時間
336 小時
最后登錄
2020-1-19
15#
2019-12-5 11:55:21 只看該作者
這個可以好好學學
回復 支持 反對

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 注冊帳號

本版積分規則

神马电影34pp影视午夜