根据MySql的表名,自动生成实体类,模仿ORM框架

ORM框架可以根据数据库的表自动生成实体类,以及相应CRUD操作

本文是一个自动生成实体类的工具,用于生成Mysql表对应的实体类。

新建Winform窗体应用程序AutoGenerateForm,框架(.net framework 4.5),

添加对System.Configuration的引用,同时添加对SqlSugar.dllMySql.Data.dll的引用。

SqlSugar是一种开源的ORM框架,可以直接在github上面下载。

将默认的Form1重命名为 FormGenerateClass。

一、在默认的App.config配置文件中配置MySql数据库连接

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <connectionStrings>
    <add name="MySqlDataConnect" connectionString="server=127.0.0.1;Database=sh_db;Uid=root;Pwd=root" />
    <add name="SqlServerDataConnect" connectionString="server=127.0.0.1;Database=ylq_db;Uid=root;Pwd=root" />
  </connectionStrings>
</configuration>

二、新建文件操作类FileContentUtil.cs,源程序如下:

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AutoGenerateForm
{
    /// <summary>
    /// 写表名.cs实体类文件操作
    /// </summary>
    public class FileContentUtil
    {
        /// <summary>
        /// Mysql列的数据类型 与 C#(CSharp)基础数据类型的映射表
        /// 元组的第一项是MySql数据类型,元组的第二项是C#数据类型
        /// </summary>
        private static List<Tuple<string, string>> MappingTypesConst = new List<Tuple<string, string>>()
        {
                    Tuple.Create("int","int"),
                    Tuple.Create("mediumint","int"),
                    Tuple.Create("integer","int"),

                    Tuple.Create("varchar","string"),
                    Tuple.Create("text","string"),
                    Tuple.Create("char","string"),
                    Tuple.Create("enum","string"),
                    Tuple.Create("mediumtext","string"),
                    Tuple.Create("tinytext","string"),
                    Tuple.Create("longtext","string"),

                    Tuple.Create("tinyint","byte"),
                    Tuple.Create("smallint","short"),
                    Tuple.Create("bigint","long"),
                    Tuple.Create("bit","bool"),
                    Tuple.Create("real","double"),
                    Tuple.Create("double","double"),
                    Tuple.Create("float","float"),
                    Tuple.Create("decimal","decimal"),
                    Tuple.Create("numeric","decimal"),
                    Tuple.Create("year","int"),

                    Tuple.Create("datetime","DateTime"),
                    Tuple.Create("timestamp","DateTime"),
                    Tuple.Create("date","DateTime"),
                    Tuple.Create("time","DateTime"),

                    Tuple.Create("blob","byte[]"),
                    Tuple.Create("longblob","byte[]"),
                    Tuple.Create("tinyblob","byte[]"),
                    Tuple.Create("varbinary","byte[]"),
                    Tuple.Create("binary","byte[]"),
                    Tuple.Create("multipoint","byte[]"),
                    Tuple.Create("geometry","byte[]"),
                    Tuple.Create("multilinestring","byte[]"),
                    Tuple.Create("polygon","byte[]"),
                    Tuple.Create("mediumblob","byte[]"),

                    //Tuple.Create("varchar","Guid"),
        };

        /// <summary>
        /// 获取C#的数据类型字符串
        /// 如果列是值类型,并且允许空,则需要在类型后加一个问号,如int?
        /// 如果列是引用类型,或者【值类型 并且 不为空】,则类型后面不加问号,如 string
        /// </summary>
        /// <param name="dataType"></param>
        /// <param name="IsNullable"></param>
        /// <returns></returns>
        private static string GetDataTypeString(string dataType, string isNullable)
        {
            string result = "object";
            Tuple<string, string> keyValue = MappingTypesConst.Find(tuple => tuple.Item1 == dataType.ToLower());
            if (keyValue != null)
            {
                result = keyValue.Item2;
            }

            //如果是值类型 并且 允许空。则为 可空值类型,类型后面加个?。如int? 就是 Nullable<int>
            if (result != "string" && result != "byte[]" && result != "object" && isNullable == "1")
            {
                result += "?";
            }
            return result;
        }

        /// <summary>
        /// 获取tableName.cs文件的全部内容文本
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="tableComment">表的注释说明</param>
        /// <param name="dataTable">表的所有列信息:类型、列名、列的注释说明</param>
        /// <returns></returns>
        public static string GetFileContent(string tableName, string tableComment, DataTable dataTable)
        {
            string namespaceString = @"using System;
using System.Linq;
using System.Text;

namespace AutoGenerateForm.Models
{";
            string classString = $@"
    ///<summary>
    /// {tableComment}
    ///</summary>
    public class {tableName}
    {
   
   {
";
            StringBuilder sb = new StringBuilder(namespaceString);
            sb.Append(classString);
            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                string dataType = dataTable.Rows[i]["DataType"].ToString();
                string columnName = dataTable.Rows[i]["DbColumnName"].ToString();
                string columnComment = dataTable.Rows[i]["ColumnComment"].ToString();
                string isNullable = dataTable.Rows[i]["IsNullable"].ToString();
                string isPrimaryKey = dataTable.Rows[i]["IsPrimaryKey"].ToString();
                dataType = GetDataTypeString(dataType, isNullable);
                if (string.IsNullOrEmpty(columnComment))
                {
                    //如果列的注释为空,则使用列名作为注释
                    columnComment = columnName;
                }
                //是否条码列
                bool isBarcodeField = columnName.IndexOf("PackBarcode", StringComparison.CurrentCultureIgnoreCase) >= 0;
                string attributeMessage = "";
                if (isPrimaryKey == "1")
                {
                    //如果是主键,增加特性 【主键】
                    attributeMessage = Environment.NewLine + "        [SqlSugar.SugarColumn(IsPrimaryKey = true)]";
                }
                else if (isBarcodeField)
                {
                    //如果是条码列,增加特性 【列描述是Barcode】
                    attributeMessage = Environment.NewLine + "        [SqlSugar.SugarColumn(ColumnDescription = \"Barcode\")]";
                }
                sb.AppendLine($@"        /// <summary>
        /// {columnComment}
        /// </summary>{attributeMessage}
        public {dataType} {columnName} {
   
   { get; set; }}");
            }

            //增加类和命名空间的结束右大括号
            sb.Append(@"    }
}");
            return sb.ToString();
        }

        /// <summary>
        /// 创建一个文件,并将字符串写入文件。
        /// </summary>
        /// <param name="filePath">文件的绝对路径</param>
        /// <param name="text">字符串数据</param>
        /// <param name="encoding">字符编码</param>
        public static void CreateFile(string filePath, string text, Encoding encoding)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
                //如果文件不存在则创建该文件
                if (!File.Exists(filePath))
                {
                    //实例化文件
                    FileInfo file = new FileInfo(filePath);
                    //获取文件目录路径
                    string fileDirectory = file.DirectoryName;
                    //如果文件的目录不存在,则创建目录
                    if (!Directory.Exists(fileDirectory))
                    {
                        Directory.CreateDirectory(fileDirectory);
                    }
                    //创建文件
                    using (FileStream stream = file.Create())
                    {
                        using (StreamWriter writer = new StreamWriter(stream, encoding))
                        {
                            //写入字符串     
                            writer.Write(text);
                            //输出
                            writer.Flush();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"创建文件出现异常:{ex.Message}");
            }
        }
    }
}

三、使用SqlSugar操作MySql的两个相关类 SugarDao.cs用于数据库连接,源程序:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using SqlSugar;

namespace AutoGenerateForm
{
    /// <summary>
    /// SqlSugar
    /// </summary>
    public class SugarDao
    {
        //禁止实例化
        private SugarDao()
        {

        }

        /// <summary>
        /// 需添加对System.Configuration的引用
        /// </summary>
        /// <param name="index">1为Mysql连接 2为SqlServer连接</param>
        /// <returns></returns>
        public static string ConnectionString(int index = 1)
        {
            string reval = "server=localhost;Database=eve_db;Uid=root;Pwd=12345"; //这里可以动态根据cookies或session实现多库切换
            if (index == 1)
                reval = System.Configuration.ConfigurationManager.ConnectionStrings["MySqlDataConnect"].ConnectionString;//连接字符串
            else if (index == 2)
                reval = System.Configuration.ConfigurationManager.ConnectionStrings["SqlServerDataConnect"].ConnectionString;//连接字符串
            return reval;
        }
        public static SqlSugarClient GetInstance(SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
        {
            return new SqlSugarClient(new ConnectionConfig()
            {
                DbType = dbType,
                ConnectionString = ConnectionString(index),
                InitKeyType = InitKeyType.Attribute,
                IsAutoCloseConnection = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuting = (sql, p) =>
                    {
                        Console.WriteLine(sql);
                        Console.WriteLine(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
                    }
                }
            });
        }
        /// <summary>
        /// 检查数据库连接
        /// </summary>
        public static void CheckConnect()
        {
            var db = GetInstance();
            db.Open();
        }
    }
}

四、第二个类RawSql.cs,用于执行sql相关操作,源程序

using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AutoGenerateForm
{
    /// <summary>
    /// 原生的sql增删改查
    /// </summary>
    public class RawSql
    {
        /// <summary>
        /// 执行原生的Sql与sql参数的insert、update、delete等操作,返回受影响的行数
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="dict"></param>
        /// <param name="dbType">数据库类型,一般是mysql</param>
        /// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
        /// <returns></returns>
        public static int ExecuteCommand(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
        {
            List<SugarParameter> parameters = DictToList(dict);
            using (var db = SugarDao.GetInstance(dbType, index))
            {
                return db.Ado.ExecuteCommand(sql, parameters);
            }
        }

        /// <summary>
        /// 执行原生的Sql与sql参数的select查询等操作,返回首行首列的数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="dict"></param>
        /// <param name="dbType">数据库类型,一般是mysql</param>
        /// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
        /// <returns></returns>
        public static object GetScalar(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
        {
            List<SugarParameter> parameters = DictToList(dict);
            using (var db = SugarDao.GetInstance(dbType, index))
            {
                return db.Ado.GetScalar(sql, parameters);
            }
        }

        /// <summary>
        /// 执行原生的Sql与sql参数的select查询等操作,返回一个数据表
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="dict"></param>
        /// <param name="dbType">数据库类型,一般是mysql</param>
        /// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
        /// <returns></returns>
        public static DataTable GetDataTable(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
        {
            List<SugarParameter> parameters = DictToList(dict);
            using (var db = SugarDao.GetInstance(dbType, index))
            {
                return db.Ado.GetDataTable(sql, parameters);
            }
        }

        /// <summary>
        /// 字典转参数列表
        /// </summary>
        /// <param name="dict"></param>
        /// <returns></returns>
        private static List<SugarParameter> DictToList(Dictionary<string, object> dict)
        {
            List<SugarParameter> parameters = new List<SugarParameter>();
            for (int i = 0; dict != null && i < dict.Count; i++)
            {
                KeyValuePair<string, object> keyValuePair = dict.ElementAt(i);
                parameters.Add(new SugarParameter(keyValuePair.Key, keyValuePair.Value));
            }
            return parameters;
        }
    }
}

五、窗体FormGenerateClass.cs 设计如下:

窗体的FormGenerateClass.cs主要代码如下(忽略设计器自动生成的代码):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AutoGenerateForm
{
    public partial class FormGenerateClass : Form
    {
        public FormGenerateClass()
        {
            InitializeComponent();
        }

        private void btnGenerate_Click(object sender, EventArgs e)
        {
            rtxbClassContent.Clear();
            if (cboTable.SelectedIndex == -1)
            {
                cboTable.Focus();
                DisplayInfo("没有选择相应的表名,请检查...");                
                return;
            }
            string tableName = Convert.ToString(cboTable.SelectedValue);
            string tableComment = cboTable.Text;
            DisplayInfo($"已选择表【{tableName}】,准备自动生成实体类...");
            string sql = $@"SELECT TABLE_NAME as TableName, 
                     column_name AS DbColumnName,
                     CASE WHEN  left(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)-1)='' THEN COLUMN_TYPE ELSE  left(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)-1) END AS DataType,
                     CAST(SUBSTRING(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)+1,LOCATE(')',COLUMN_TYPE)-LOCATE('(',COLUMN_TYPE)-1) AS signed) AS Length,
                     column_default  AS  `DefaultValue`,
                     column_comment  AS  `ColumnComment`,
                     CASE WHEN COLUMN_KEY = 'PRI' THEN true ELSE false END AS `IsPrimaryKey`,
                     CASE WHEN EXTRA='auto_increment' THEN true ELSE false END as IsIdentity,
                     CASE WHEN is_nullable = 'YES' THEN true ELSE false END AS `IsNullable`
                     FROM Information_schema.columns where TABLE_NAME='{tableName}' and  TABLE_SCHEMA=(select database()) ORDER BY TABLE_NAME";
            DataTable dataTable = RawSql.GetDataTable(sql, null);
            if (dataTable == null || dataTable.Rows.Count == 0)
            {
                DisplayInfo($"没有找到表【{tableName}】的字段(列)信息...");
                return;
            }

            string fileDirectory = AppDomain.CurrentDomain.BaseDirectory + @"AutoGenerateCodes\Models";//生成到的路径
            string filePath = $"{Path.Combine(fileDirectory, tableName)}.cs";
            string text = FileContentUtil.GetFileContent(tableName, tableComment, dataTable);
            FileContentUtil.CreateFile(filePath, text, Encoding.UTF8);
            DisplayInfo($"自动生成实体类【{tableName}】成功.实体类路径:{filePath}");
            rtxbClassContent.AppendText(text);
        }

        private void FormGenerateClass_Load(object sender, EventArgs e)
        {
            string sqlAllTables = "SELECT TABLE_SCHEMA,TABLE_NAME,TABLE_TYPE,CREATE_TIME,TABLE_COMMENT FROM information_schema.`TABLES` where TABLE_SCHEMA = (select database())";
            DataTable dataTable = RawSql.GetDataTable(sqlAllTables, null);
            BindingSource bindingSource = new BindingSource();
            bindingSource.DataSource = dataTable;
            cboTable.DataSource = bindingSource;
            cboTable.ValueMember = "TABLE_NAME";
            cboTable.DisplayMember = "TABLE_COMMENT";
        }

        /// <summary>
        /// 显示文本框的消息
        /// </summary>
        /// <param name="message"></param>
        private void DisplayInfo(string message)
        {
            this.BeginInvoke(new Action(() =>
            {
                if (rtxbResult.TextLength >= 20480)
                {
                    rtxbResult.Clear();
                }
                rtxbResult.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} --> {message}\n");
                rtxbResult.ScrollToCaret();
            }));
        }
    }
}

六、程序运行如图:

猜你喜欢

转载自blog.csdn.net/ylq1045/article/details/116170440