zhang273162308 Unity实用小工具或脚本—以对象形式操作Sqlite数据库(一)

24
回复
849
查看
打印 上一主题 下一主题
[ 复制链接 ]
排名
141
昨日变化

125

主题

596

帖子

7052

积分

Rank: 9Rank: 9Rank: 9

UID
3579
好友
110
蛮牛币
5726
威望
0
注册时间
2013-9-10
在线时间
1598 小时
最后登录
2020-2-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蛮牛粉丝
1404/1500
排名
1960
昨日变化

2

主题

321

帖子

1404

积分

Rank: 6Rank: 6Rank: 6

UID
147717
好友
0
蛮牛币
2115
威望
0
注册时间
2016-5-5
在线时间
391 小时
最后登录
2020-1-17
沙发
2019-11-29 15:37:29 只看该作者
学习了  感谢分享

点评

是的  发表于 2019-12-14 21:14
6蛮牛粉丝
1063/1500
排名
3929
昨日变化

0

主题

329

帖子

1063

积分

Rank: 6Rank: 6Rank: 6

UID
251353
好友
0
蛮牛币
7757
威望
0
注册时间
2017-10-29
在线时间
354 小时
最后登录
2020-1-16
板凳
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
蛮牛币
83
威望
0
注册时间
2016-3-23
在线时间
140 小时
最后登录
2020-1-18
6#
2019-11-30 15:35:18 只看该作者
66666666666学习学习学习
5熟悉之中
626/1000
排名
6777
昨日变化

15

主题

97

帖子

626

积分

Rank: 5Rank: 5

UID
265691
好友
1
蛮牛币
5077
威望
0
注册时间
2018-1-22
在线时间
308 小时
最后登录
2020-2-19
7#
2019-12-2 08:29:38 只看该作者
谢谢大佬分享知识
7日久生情
4399/5000
排名
62
昨日变化

0

主题

344

帖子

4399

积分

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

UID
61610
好友
0
蛮牛币
4888
威望
0
注册时间
2014-12-16
在线时间
1253 小时
最后登录
2020-2-22
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日久生情
2415/5000
排名
1621
昨日变化

0

主题

776

帖子

2415

积分

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

UID
148286
好友
0
蛮牛币
4270
威望
0
注册时间
2016-5-11
在线时间
838 小时
最后登录
2020-1-20
9#
2019-12-2 09:26:17 只看该作者
7日久生情
1863/5000
排名
2307
昨日变化

6

主题

397

帖子

1863

积分

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

UID
175097
好友
5
蛮牛币
2623
威望
0
注册时间
2016-10-12
在线时间
836 小时
最后登录
2020-2-21
10#
2019-12-2 09:28:49 只看该作者
学习~~~~~~~~~
7日久生情
1863/5000
排名
2307
昨日变化

6

主题

397

帖子

1863

积分

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

UID
175097
好友
5
蛮牛币
2623
威望
0
注册时间
2016-10-12
在线时间
836 小时
最后登录
2020-2-21
11#
2019-12-2 09:31:07 只看该作者
学习~~~~~~~~~~~~~~~~~~~~~~~~~~~
6蛮牛粉丝
1018/1500
排名
3990
昨日变化

2

主题

156

帖子

1018

积分

Rank: 6Rank: 6Rank: 6

UID
246321
好友
0
蛮牛币
7416
威望
0
注册时间
2017-9-27
在线时间
486 小时
最后登录
2020-2-9
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 只看该作者
看不懂 不过看起来很专业
排名
64939
昨日变化

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 只看该作者
这个可以好好学学
您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

,