Unity 连接 MySQL 方法

📅 4月16日 / 🎨 开发日志 / 👓 38 / 💬 4


首先在 MySQL 官网下载 Connector

注意要选择 .NET & Mono 版本。

解压后将以下两个文件放入U3D项目的 Assets\Plugins 文件夹

  1. MySql.Data.dll
  2. Google.Protobuf.dll

即可。


附:MySQL 操作封装类:

为了快速测试,我在网上找了一些封装好的类。但由于方案变化没再使用。此封装类可能存在一些缺陷,仅供测试。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using MySql.Data.MySqlClient;
using System.Data;
using System.Text;

/// <summary>
/// Unity连接MySQL的工具类,项目无关,已封装基本SQL语句,可按需自行扩展,执行完一次数据操作后务必关闭数据库连接   
/// </summary>
public class MySQLAccessUtility
{

    static MySqlConnection mySqlConnection;
    static string host;
    static string port;
    static string userName;
    static string password;
    static string databaseName;


    public MySQLAccessUtility(string _host, string _port, string _userName, string _password, string _databaseName)
    {
        host = _host;
        port = _port;
        userName = _userName;
        password = _password;
        databaseName = _databaseName;
    }

    public void OpenMySQL()
    {
        try
        {
            string sqlString = string.Format("Database={0};Data Source={1};User Id={2};Password={3};port={4}", databaseName, host, userName, password, port);
            mySqlConnection = new MySqlConnection(sqlString);
            mySqlConnection.Open();
            //Debug.Log("连接成功");
        }
        catch (Exception e)
        {
            throw new Exception("请查看MySQL数据库是否开启" + e.Message.ToString());
        }
    }

    public void CloseMySQL()
    {
        if (mySqlConnection != null)
        {
            mySqlConnection.Close();
            mySqlConnection.Dispose();
            mySqlConnection = null;
        }
    }

    /// <summary>
    /// select语句的生成方法
    /// </summary>
    /// <param name="columns">需要选择的列</param>
    /// <param name="tableName">表名</param>
    /// <param name="constrainedColumns">条件约束的列</param>
    /// <param name="constrainOperation">条件约束的操作符</param>
    /// <param name="value">条件的值</param>
    /// <returns>查询结果的DataSet类</returns>
    public DataSet Select(string[] columns, string tableName, string[] constrainedColumns = null, string[] constrainedOperations = null, string[] values = null)
    {
        if (constrainedColumns == null)
            constrainedColumns = new string[] { };
        if (constrainedOperations == null)
            constrainedOperations = new string[] { };
        if (values == null)
            values = new string[] { };

        if (constrainedColumns.Length != constrainedOperations.Length || constrainedColumns.Length != values.Length)
        {
            throw new Exception("条件输入有误,条件约束列、操作符、值的数量不一致");
        }

        StringBuilder sqlSentence = new StringBuilder("select ");
        for (int i = 0; i < columns.Length; i++)
        {
            if (i > 0)
                sqlSentence.Append(", ");
            sqlSentence.Append(columns[i]);
        }

        sqlSentence.Append(" from " + tableName);
        if (constrainedColumns.Length > 0)
            sqlSentence.Append(" where ");
        for (int i = 0; i < constrainedColumns.Length; i++)
        {
            if (i > 0)
                sqlSentence.Append(" and ");
            sqlSentence.Append(constrainedColumns[i] + constrainedOperations[i] + values[i]);
        }

        return ExecuteSQL(sqlSentence);
    }

    /// <summary>
    /// 插入语句
    /// </summary>
    /// <param name="tableName">表名</param>
    /// <param name="values">要插入各列的字符数组列表</param>
    public void Insert(string tableName, List<string[]> values)
    {
        if(values == null)
            throw new Exception("条件输入有误,未指定插入的值");

        StringBuilder sqlSentence = new StringBuilder("insert into ");
        sqlSentence.Append(tableName + " values");
        for (int i = 0; i < values.Count; i++)
        {
            sqlSentence.Append("(");
            for (int j = 0; j < values[i].Length; j++)
            {
                sqlSentence.Append("'" + values[i][j].Replace("\'", "‘") + "'");
                if (j < values[i].Length - 1)
                    sqlSentence.Append(",");
            }
            sqlSentence.Append(")");
            if (i < values.Count - 1)
                sqlSentence.Append(",");
        }

        ExecuteSQL(sqlSentence);
    }

    /// <summary>
    /// 通过id删除行
    /// </summary>
    /// <param name="tableName">表名</param>
    /// <param name="ids">需要删除行的id数组,为空则清空全表</param>
    public void Delete(string tableName, List<string> ids = null)
    {
        StringBuilder sqlSentence = new StringBuilder("delete from ");
        sqlSentence.Append(tableName);

        if (ids.Count > 0)
        {
            sqlSentence.Append(" where id in (");
            for (int i = 0; i < ids.Count-1; i++)
            {
                sqlSentence.Append(ids[i] + ", ");
            }
            sqlSentence.Append(ids[ids.Count - 1] + ")");
        }

        ExecuteSQL(sqlSentence);
    }


    public void CreateTable(string tableName, string[] columns)
    {
        StringBuilder sqlSentence = new StringBuilder(string.Format("create table if not exists {0} (", tableName));

        for (int i = 0; i < columns.Length; i++)
        {
            string variety;
            if (i == 0)
                variety = "int not null";
            if (i == 3)
                variety = "text";
            else
                variety = " varchar(255)";
            sqlSentence.Append(string.Format("{0} {1}, ", columns[i], variety));
        }
        sqlSentence.Append(string.Format("primary key ({0}))", columns[0]));

        ExecuteSQL(sqlSentence);
    }

    /// <summary>
    /// 执行生成的SQL语句
    /// </summary>
    /// <param name="sqlSentence">生成的SQL语句</param>
    /// <returns>查询结果的DataSet类</returns>
    DataSet ExecuteSQL(StringBuilder sqlSentence)
    {
        //Debug.Log(sqlSentence.ToString());
        OpenMySQL();

        if (mySqlConnection.State == ConnectionState.Open)
        {
            DataSet ds = new DataSet();
            try
            {
                MySqlDataAdapter mySqlDataAdapter = new MySqlDataAdapter(sqlSentence.ToString(), mySqlConnection);  
                mySqlDataAdapter.Fill(ds);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message.ToString());
            }
            finally
            {
            }

            return ds;
        }

        CloseMySQL();

        return null;
    }

}

Update(20190920):

鉴于评论在讨论这个封装类的问题,我也多说两句。一般情况下个人是不建议用 Unity 直连数据库的(除非是针对单台主机定制的项目),否则这样做之后扩展性会降低很多,给后续项目的部署带来很多麻烦。当然用什么方案还是取决于业务性质。这里我只把以前做方案时的测试结果贴出来,以备以后需要(不过不太可能了)。
(完)

留言(4)

A
AChrome 74.0Win7#83
4天前 回复

1、类必须实例化使用,每个实例在构造的时候却要影响静态成员。
2、所有实例使用的时候都是同一个 mySqlConnection(静态成员),可能问题:第一个实例把连接打开,第二个实例执行完毕把连接关闭。
3、该类使用的时候不支持 using 语句,所以手动写 try finally, CloseMySQL() 方法大部分都要在 finally 块调用。

Juexe
JuexeChrome 74.0Win10#84
4天前

多谢大佬指正

田园野望者
田园野望者Chrome 74.0Win10#85
2天前 回复

博主展示的是最原始的ado.net的连接方式,其实C#有很多封装的orm可以使用,比如sqlsugar dapper,EF(太大了,不建议使用),可以封装一个连接数据库的上下文类,把连接数据库的相关字符串放置在配置项中。当然没用过unity,但是我想C#都可以这么操作吧。

Juexe
JuexeChrome 74.0Win10#86
2天前

多谢补充。因为 .NET 框架的具体实现有所不同,Unity 使用的是 Mono.NET,所以虽然语言层面同是 C# 但有些方法可能不通用。找到了一篇很好的文章

没有更多了 :)