找回密码
 注册帐号

扫一扫,访问微社区

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

14
回复
156
查看
[ 复制链接 ]
排名
141
昨日变化

125

主题

596

帖子

7033

积分

Rank: 9Rank: 9Rank: 9

UID
3579
好友
109
蛮牛币
5617
威望
0
注册时间
2013-9-10
在线时间
1581 小时
最后登录
2019-12-6

专栏作家活力之星游戏蛮牛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文件拖到这个文件夹下,如图所示:
托人到Unity中.png
导入之后出现如下错误:这个意思是有导入的dll文件不适合当前Unity设置的.Net版本。
导入错误1.png
选中System.Data文件,修改它为如图所示:
SystemData的配置修改.png
下载sqlite3文件sqlite3.dll下载地址,选择适合PC平台电脑系统位数的文件,我选择下载的文件如图所示:
sqlite下载示意图.png
并将下载好的文件也托人到unity的Plugin文件下,该文件导入之后不需要进行配置修改。
1.3、最后在PlayerSetting里的设置如图所示:
发布配置1.png
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.png
从图中可以看到我们已经将数据插入进去了
三、总结
1、详细介绍了在unity中使用Sqliite数据库的过程和注意事项,最重要的是需要三个dll文件的导入和配置
2、改进了原来在C#里面操作Sql语句和数据进行连接并操作数据库进行增、删、改、查的操作,增加了从类直接到数据库表的数据映射操作,之后可以直接对类进行操作,由类管理和数据库底层Sql语句的代码,大大的简化了数据库操作的开发流程。
3、后续还会对数据库进行更加完善的操作,包括删除、更新和查找等
4、unity工程下载:
游客,如果您要查看本帖隐藏内容请回复

回复

使用道具 举报

6蛮牛粉丝
1387/1500
排名
1960
昨日变化

2

主题

314

帖子

1387

积分

Rank: 6Rank: 6Rank: 6

UID
147717
好友
0
蛮牛币
2019
威望
0
注册时间
2016-5-5
在线时间
381 小时
最后登录
2019-12-6
7 天前 显示全部楼层
学习了  感谢分享
回复 支持 反对

使用道具 举报

6蛮牛粉丝
1059/1500
排名
3929
昨日变化

0

主题

329

帖子

1059

积分

Rank: 6Rank: 6Rank: 6

UID
251353
好友
0
蛮牛币
7670
威望
0
注册时间
2017-10-29
在线时间
350 小时
最后登录
2019-12-6
7 天前 显示全部楼层
谢谢大佬
回复

使用道具 举报

4四处流浪
356/500
排名
5211
昨日变化

0

主题

44

帖子

356

积分

Rank: 4

UID
114753
好友
0
蛮牛币
457
威望
0
注册时间
2015-7-22
在线时间
36 小时
最后登录
2019-11-30
6 天前 显示全部楼层
感谢感谢感谢感谢感谢!支持!!
回复 支持 反对

使用道具 举报

4四处流浪
356/500
排名
5211
昨日变化

0

主题

44

帖子

356

积分

Rank: 4

UID
114753
好友
0
蛮牛币
457
威望
0
注册时间
2015-7-22
在线时间
36 小时
最后登录
2019-11-30
6 天前 显示全部楼层
感谢感谢感谢感谢感谢!支持!!支持!!
回复 支持 反对

使用道具 举报

4四处流浪
309/500
排名
20608
昨日变化

6

主题

138

帖子

309

积分

Rank: 4

UID
143117
好友
0
蛮牛币
76
威望
0
注册时间
2016-3-23
在线时间
135 小时
最后登录
2019-11-30
6 天前 显示全部楼层
66666666666学习学习学习
回复 支持 反对

使用道具 举报

5熟悉之中
623/1000
排名
6777
昨日变化

15

主题

96

帖子

623

积分

Rank: 5Rank: 5

UID
265691
好友
1
蛮牛币
5076
威望
0
注册时间
2018-1-22
在线时间
306 小时
最后登录
2019-12-4
4 天前 显示全部楼层
谢谢大佬分享知识
回复 支持 反对

使用道具 举报

7日久生情
4354/5000
排名
62
昨日变化

0

主题

342

帖子

4354

积分

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

UID
61610
好友
0
蛮牛币
4794
威望
0
注册时间
2014-12-16
在线时间
1210 小时
最后登录
2019-12-6
4 天前 显示全部楼层
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日久生情
2400/5000
排名
1621
昨日变化

0

主题

776

帖子

2400

积分

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

UID
148286
好友
0
蛮牛币
4186
威望
0
注册时间
2016-5-11
在线时间
824 小时
最后登录
2019-12-6
4 天前 显示全部楼层
回复

使用道具 举报

7日久生情
1794/5000
排名
2307
昨日变化

6

主题

390

帖子

1794

积分

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

UID
175097
好友
5
蛮牛币
2445
威望
0
注册时间
2016-10-12
在线时间
774 小时
最后登录
2019-12-6
4 天前 显示全部楼层
学习~~~~~~~~~
回复 支持 反对

使用道具 举报

7日久生情
1794/5000
排名
2307
昨日变化

6

主题

390

帖子

1794

积分

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

UID
175097
好友
5
蛮牛币
2445
威望
0
注册时间
2016-10-12
在线时间
774 小时
最后登录
2019-12-6
4 天前 显示全部楼层
学习~~~~~~~~~~~~~~~~~~~~~~~~~~~
回复 支持 反对

使用道具 举报

5熟悉之中
974/1000
排名
3990
昨日变化

2

主题

148

帖子

974

积分

Rank: 5Rank: 5

UID
246321
好友
0
蛮牛币
7130
威望
0
注册时间
2017-9-27
在线时间
450 小时
最后登录
2019-12-6
4 天前 显示全部楼层
学习了  感谢分享
回复 支持 反对

使用道具 举报

0

主题

43

帖子

53

积分

Rank: 2Rank: 2

UID
335753
好友
0
蛮牛币
71
威望
0
注册时间
2019-11-12
在线时间
10 小时
最后登录
2019-12-4
4 天前 显示全部楼层
看不懂 不过看起来很专业
回复 支持 反对

使用道具 举报

排名
64938
昨日变化

0

主题

11

帖子

16

积分

Rank: 1

UID
169072
好友
0
蛮牛币
22
威望
0
注册时间
2016-9-18
在线时间
3 小时
最后登录
2019-12-4
前天 16:01 显示全部楼层
学习了  感谢分享
回复 支持 反对

使用道具 举报

5熟悉之中
595/1000
排名
9113
昨日变化

3

主题

131

帖子

595

积分

Rank: 5Rank: 5

UID
60012
好友
0
蛮牛币
5143
威望
0
注册时间
2014-12-8
在线时间
333 小时
最后登录
2019-12-5
昨天 11:55 显示全部楼层
这个可以好好学学
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则