首页 > 数据库 >C# Sql帮助类,可扩展

C# Sql帮助类,可扩展

时间:2024-08-13 15:39:52浏览次数:17  
标签:string C# Sql 扩展 column propertyInfo null public Name


        [System.AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
        public class DbTableAttribute : Attribute
        {
            public string Name { get; set; }
            public string Charset { get; set; }
            public string Collate { get; set; }
        }
        [System.AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
        public class DbColumnAttribute : Attribute
        {
            public string Name { get; set; }
            /// <summary>
            /// <para>type[(length)] [[primary key]|[unique]] [unsigned] [zerofill] [not null or null] [default your_value] [comment 'your comment'] [collate 'your encoding'] ...etc.</para>
            /// <para>bigint auto_increment</para>
	        /// <para>int default '0'</para>
	        /// <para>varchar(50) null default null collate 'utf8_general_ci'</para>
            /// <para>datetime null</para>
            /// <para>datetime null default 'localtime'</para>
	        /// <para>timestamp not null default current_timestamp on update current_timestamp</para>
            /// <para>bit(1) null default b'0' comment 'balabala'</para>
            ///  </summary>
            public string Desc { get; set; }
            /// <summary>
            /// Index1,Indx 2,Index3,primary key,unique
            /// </summary>
            public string Index { get; set; }
            public bool NotInsert { get; set; }
        }
        public abstract class DbContext : IDisposable
        {
            protected string connectStr;
            public virtual int AddColumn<Table>(DbColumnAttribute dbColumnAttribute)
            {
                if (dbColumnAttribute == null)
                    dbColumnAttribute = new DbColumnAttribute();
                Type tableType = typeof(Table);
                DbTableAttribute dbTableAttribute = GetDbTableAttribute<Table>();
                return AddColumn(tableType.Name, dbColumnAttribute.Name, dbColumnAttribute.Desc);
            }
            public virtual int AddColumn(string tableName, string columnName, string options)
            {
                string sql = $"alter table '{tableName}' add  `{columnName}` {options}";
                int r = ExecuteNonQuery(sql);
                return r;
            }
            public virtual void AddIndex(string tableName, string index, string[] columns)
            {
                string sql = $"create index `{index}` on `{tableName}` (`{string.Join(",", columns)}`)";
                ExecuteNonQuery(sql);
            }
            public virtual void DeleteIndex(string tableName, string index)
            {
                ExecuteNonQuery($"drop index `{index}` on `{tableName}`");
            }
            public abstract int ExecuteNonQuery(string sql, params DbParameter[] parameters);
            public abstract object ExecuteScalar(string sql, params DbParameter[] parameters);
            public abstract DataTable Query(string sql, params DbParameter[] parameters);
            public virtual List<Table> GetList<Table>(string sql, params DbParameter[] parameters)
            {
                var list = new List<Table>();
                DataTable dt = Query(sql, parameters);
                if (dt == null) return list;
                Dictionary<string, PropertyInfo> dict = new Dictionary<string, PropertyInfo>();
                foreach (var propertyInfo in typeof(Table).GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    var column = propertyInfo.GetCustomAttribute<DbColumnAttribute>();
                    if (column == null) continue;
                    dict.Add(column.Name, propertyInfo);
                }
                foreach (DataRow row in dt.Rows)
                {
                    Table model = Activator.CreateInstance<Table>();
                    foreach (DataColumn column in dt.Columns)
                    {
                        if (!dict.ContainsKey(column.ColumnName)) continue;
                        var propertyInfo = dict[column.ColumnName];
                        var value = row[column.ColumnName];
                        if (value == null || value is DBNull) continue;
                        if (propertyInfo.PropertyType == typeof(int))
                            propertyInfo.SetValue(model, Convert.ToInt32(value));
                        else if (propertyInfo.PropertyType == typeof(byte))
                            propertyInfo.SetValue(model, Convert.ToByte(value));
                        else if (propertyInfo.PropertyType == typeof(long))
                            propertyInfo.SetValue(model, Convert.ToInt64(value));
                        else if (propertyInfo.PropertyType == typeof(float))
                            propertyInfo.SetValue(model, Convert.ToSingle(value));
                        else if (propertyInfo.PropertyType == typeof(double))
                            propertyInfo.SetValue(model, Convert.ToDouble(value));
                        else if (propertyInfo.PropertyType == typeof(decimal))
                            propertyInfo.SetValue(model, Convert.ToDecimal(value));
                        else if (propertyInfo.PropertyType == typeof(DateTime))
                            propertyInfo.SetValue(model, Convert.ToDateTime(value));
                        else if (propertyInfo.PropertyType == typeof(string))
                            propertyInfo.SetValue(model, value.ToString());
                        else if (propertyInfo.PropertyType.IsEnum)
                            propertyInfo.SetValue(model, Enum.Parse(propertyInfo.PropertyType, value.ToString()));
                    }
                    list.Add(model);
                }
                return list;
            }
            public abstract void Connect(bool reconnect = false);
            public abstract int CreateTable<Table>();
            public abstract bool ExistColumn(string column, string table);
            public abstract bool ExistIndex(string tableName, string index, string columnName = null);
            public abstract bool ExistTable(string table);
            public virtual Dictionary<string, List<string>> GetIndexs(Type table)
            {
                Dictionary<string, List<string>> indexDict = new Dictionary<string, List<string>>();
                foreach (var propertyInfo in table.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    var column = propertyInfo.GetCustomAttribute<DbColumnAttribute>();
                    if (column == null) continue;
                    if (!string.IsNullOrWhiteSpace(column.Index))
                    {
                        foreach (var index in column.Index.Split(','))
                        {
                            if (!indexDict.ContainsKey(index))
                                indexDict.Add(index, new List<string> { column.Name });
                            else
                                indexDict[index].Add(column.Name);
                        }
                    }
                }
                return indexDict;
            }
            public virtual void UseServer(string connectStr)
            {
                this.connectStr = connectStr;
                Connect(true);
            }
            public virtual void Repair<Table>()
            {
                var table = GetDbTableAttribute<Table>();
                var tableType = typeof(Table);
                ValidateTableAttribute(table, tableType);
                bool exist = ExistTable(table.Name);
                if (!exist)
                    CreateTable<Table>();
                else
                {
                    foreach (var propertyInfo in typeof(Table).GetProperties(BindingFlags.Instance | BindingFlags.Public))
                    {
                        var column = propertyInfo.GetCustomAttribute<DbColumnAttribute>();
                        if (column == null) continue;
                        if (ExistColumn(column.Name, table.Name))
                            AddColumn(table.Name, column.Name, column.Desc);
                    }
                    RepairIndex(tableType);
                }
            }
            public virtual void RepairIndex(Type table)
            {
                Dictionary<string, List<string>> indexDict = GetIndexs(table);
                foreach (var index in indexDict.Keys)
                {
                    foreach (var column in indexDict[index])
                    {
                        if (!ExistIndex(table.Name, index, column))
                        {
                            if (ExistIndex(table.Name, index))
                                DeleteIndex(table.Name, index);
                            AddIndex(table.Name, index, indexDict[index].ToArray());
                            break;
                        }
                    }
                }
            }
            public abstract void Dispose();
            public virtual DbTableAttribute GetDbTableAttribute<Table>()
            {
                Type t = typeof(Table);
                var tableAttribute = t.GetCustomAttribute<DbTableAttribute>();
                if (tableAttribute == null)
                    tableAttribute = new DbTableAttribute();
                ValidateTableAttribute(tableAttribute, t);
                return tableAttribute;
            }
            public abstract void ValidateTableAttribute(DbTableAttribute tableAttribute, Type type);
            public abstract int Insert<Table>(Table model);
            public abstract int DeleteByPrimaryKey<Table>(object value);
            public abstract int Delete(string table, string column, object value);
            public abstract void BeginTransaction();
            public abstract bool EndTransaction();
        }
        public class MySqlDbContext : DbContext
        {
            MySqlTransaction transaction = null;
            private MySqlConnection connection;
            public MySqlConnection Connection
            {
                get { return connection; }
                set { connection = value; }
            }

            public override void Dispose()
            {
                transaction?.Dispose();
                Connection?.Dispose();
            }
            public override void Connect(bool reconnect = false)
            {
                if (!reconnect && Connection != null && Connection.State != System.Data.ConnectionState.Closed)
                    return;
                Connection?.Dispose();
                Connection = new MySqlConnection(this.connectStr);
                Connection.Open();
            }
            public override int CreateTable<Table>()
            {
                Type tableType = typeof(Table);
                var tableAttribute = GetDbTableAttribute<Table>();
                StringBuilder sb = new StringBuilder($"create table `{tableAttribute.Name}`");
                StringBuilder columns = new StringBuilder();
                StringBuilder sbIndex = new StringBuilder();
                Dictionary<string, List<string>> indexDict = GetIndexs(tableType);
                var propertyInfos = tableType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    var columnInfo = propertyInfo.GetCustomAttribute<DbColumnAttribute>();
                    if (columnInfo == null) continue;
                    columns.AppendLine($"\t`{columnInfo.Name}` {columnInfo.Desc},");
                }
                foreach (var key in indexDict.Keys)
                {
                    string indexType = "index";
                    switch (key.ToLower().Trim())
                    {
                        case "primary":
                        case "primary key":
                        case "primarykey":
                        case "unique":
                        case "unique index":
                            continue;
                        default:
                            break;
                    }
                    sbIndex.AppendLine($"\t{indexType} `{key}` (`{string.Join("`,`", indexDict[key])}`),");
                }
                string sIndexs = sbIndex.ToString();
                string sColumns = columns.ToString();
                if (sbIndex.Length > 0)
                    sIndexs = sIndexs.Remove(sIndexs.LastIndexOf(','), 1);
                else
                    sColumns = sColumns.Remove(sColumns.LastIndexOf(','), 1);
                string content = sColumns + sIndexs;
                sb.Append($" (\r\n{content})\r\n");
                if(!string.IsNullOrWhiteSpace(tableAttribute.Charset))
                    sb.AppendLine($"default character set {tableAttribute.Charset}");
                if (!string.IsNullOrWhiteSpace(tableAttribute.Collate))
                    sb.AppendLine($"collate {tableAttribute.Collate}");
                return ExecuteNonQuery(sb.ToString());
            }
            public override void ValidateTableAttribute(DbTableAttribute tableAttribute, Type type)
            {
                if(string.IsNullOrWhiteSpace(tableAttribute.Name))
                    tableAttribute.Name = type.Name;
                if (string.IsNullOrWhiteSpace(tableAttribute.Charset))
                    tableAttribute.Charset = "utf8mb4";
                if (string.IsNullOrWhiteSpace(tableAttribute.Collate))
                    tableAttribute.Collate = "utf8mb4_unicode_ci";
            }
            public override bool ExistColumn(string column, string table)
            {
                Connect();
                var r = ExecuteScalar($"select 1 from information_schema.columns where table_schema='{Connection.Database}' and table_name ='{table}' and column_name='{column}';");
                return r != null && r.ToString() == "1";
            }
            public override bool ExistIndex(string tableName, string index, string columnName = null)
            {
                StringBuilder sql = new StringBuilder($"select count(*) from information_schema.statistics where table_schema = database() and table_name = '{tableName}' and index_name = '{index}'");
                if (!string.IsNullOrWhiteSpace(columnName))
                    sql.Append($" and column_name='{columnName}'");
                object r = ExecuteScalar(sql.ToString());
                return r != null && (r is int num) && num > 0;
            }
            public override bool ExistTable(string table)
            {
                Connect();
                var r = ExecuteScalar($"select 1 from information_schema.tables where table_schema='{Connection.Database}' and table_name ='{table}';");
                return r != null && r.ToString() == "1";
            }
            public override int ExecuteNonQuery(string sql, params DbParameter[] parameters)
            {
                Connect();
                int i;
                using (MySqlCommand cmd = new MySqlCommand(sql, Connection))
                {
                    if(this.transaction != null)
                        cmd.Transaction = this.transaction;
                    if (parameters != null && parameters.Length > 0)
                        cmd.Parameters.AddRange(parameters);
                    i = cmd.ExecuteNonQuery();
                }
                return i;
            }
            public override object ExecuteScalar(string sql, params DbParameter[] parameters)
            {
                Connect();
                using (MySqlCommand cmd = new MySqlCommand(sql, Connection))
                {
                    if (parameters != null && parameters.Length > 0)
                        cmd.Parameters.AddRange(parameters);
                    return cmd.ExecuteScalar();
                }
            }
            public override int Insert<Table>(Table model)
            {
                Type tableType = typeof(Table);
                var propertyInfos = tableType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                Dictionary<string, object> dict = new Dictionary<string, object>();
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    var columnInfo = propertyInfo.GetCustomAttribute<DbColumnAttribute>();
                    if(columnInfo == null || columnInfo.NotInsert) continue;
                    dict.Add(columnInfo.Name, propertyInfo.GetValue(model));
                }
                DbTableAttribute dbTableAttribute = GetDbTableAttribute<Table>();
                StringBuilder sb = new StringBuilder($"insert into {dbTableAttribute.Name}");
                sb.Append(string.Join(",", "(", dict.Keys.Select(s => $"{s}=@{s}"), ")"));
                sb.Append(string.Join(",", "(", dict.Keys.Select(s => $"@{s}"), ")"));
                MySqlParameter[] parameters = new MySqlParameter[dict.Count];
                int i = 0;
                using (var enumerator = dict.GetEnumerator())
                {
                    KeyValuePair<string, object> item;
                    while (enumerator.MoveNext())
                    {
                        item = enumerator.Current;
                        parameters[i++] = new MySqlParameter($"@{item.Key}", item.Value);
                    }
                }
                return ExecuteNonQuery(sb.ToString());
            }
            public override int DeleteByPrimaryKey<Table>(object value)
            {
                Type type= typeof(Table);
                var tableInfo = type.GetCustomAttribute<DbTableAttribute>();
                if (tableInfo == null) return 0;
                var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                DbColumnAttribute columnInfo;
                foreach ( var propertyInfo in properties )
                {
                    columnInfo = propertyInfo.GetCustomAttribute<DbColumnAttribute>();
                    if ( columnInfo == null || !columnInfo.Desc.ToLower().Contains("primary key")) continue;
                    return Delete(tableInfo.Name, columnInfo.Name, value);
                }
                return 0;
            }
            public override int Delete(string table, string column, object value)
            {
                return ExecuteNonQuery($"delete from `{table}` where `{column}`=@{column}", new MySqlParameter($"@{column}", value));
            }
            public override DataTable Query(string sql, params DbParameter[] parameters)
            {
                using (MySqlCommand cmd = new MySqlCommand(sql, Connection))
                {
                    cmd.Parameters.AddRange(parameters);
                    using (MySqlDataAdapter command = new MySqlDataAdapter(cmd))
                    {
                        DataSet ds = new DataSet();
                        command.Fill(ds, "ds");
                        return ds.Tables.Count > 0 ? ds.Tables[0] : null;
                    }
                }
            }
            public override void BeginTransaction()
            {
                Connect();
                transaction = Connection.BeginTransaction();
            }
            public override bool EndTransaction()
            {
                bool r;
                try
                {
                    transaction.Commit();
                    r = true;
                }
                catch
                {
                    transaction.Rollback();
                    r = false;
                }
                transaction.Dispose();
                transaction = null;
                return r;
            }
        }

使用方法:

[DbTable(Name = "account")]
public class Account
{
    [DbColumn(Name = "id", Desc = "bigint primary key auto_increment", NotInsert = true)]
    public long Id { get; set; }
    [DbColumn(Name = "un", Desc = "varchar(50) not null unique", Index = "un")]
    public string Username { get; set; }
    [DbColumn(Name = "pwd", Desc = "varchar(20) not null")]
    public string Password { get; set; }
    [DbColumn(Name = "is_deleted", Desc = "int(1) default '0")]
    public bool Deleted { get; set; }
    [DbColumn(Name = "create_time", Desc = "timestamp default localtime")]
    public DateTime CreateTime { get; set; }
}
static void Main(string[] args)
{
    MySqlDbContext dbContext = new MySqlDbContext();
    dbContext.UseServer("Data Source=127.0.0.1; Database=tempdb; User ID=admin; Password=123;Charset=utf8mb4;");
    dbContext.Repair<Account>();
    var account = new Account();
    dbContext.Insert(account);
    var list = dbContext.GetList<Account>("select * from account limit 10");
    dbContext.DeleteByPrimaryKey<Account>(account.Id);
    Console.WriteLine("按任意键退出。");
    Console.ReadKey();
}

 

标签:string,C#,Sql,扩展,column,propertyInfo,null,public,Name
From: https://www.cnblogs.com/RedSky/p/18357045

相关文章

  • 单元测试框架 powermock
    单元测试框架powermock  在pom.xml加入依赖包:<dependency><groupId>org.powermock</groupId><artifactId>powermock-api-mockito2</artifactId><version>${powermock.version}</version><scope>test</scope&......
  • 猪脸识别、自动投喂!Apache DolphinScheduler还能做这些?
    数字化转型提速中!传统农牧食品行业也寻求搭上数字化转型的快车,通过物联网、大数据、人工智能等现代信息技术,实现生产、加工、流通等环节的智能化和自动化,提高生产效率、优化资源配置、提升产品质量,并满足消费者对食品安全和可追溯性的需求。在数字化浪潮的推动下,铁骑力士集团作......
  • 随机森林分类器(Random Forest Classifier)
    随机森林分类器(RandomForestClassifier,又称为“随机森林”)是一种常用的机器学习算法,它是基于决策树的一种集成学习方法,是一种集成算法(EnsembleLearning),它属于Bagging类型,通过组合多个弱分类器,最终结果通过投票或取均值,使得整体模型的结果具有较高的精确度和泛化性能。......
  • To create a new mock, the existing static mock registration must be deregistered
    1、异常提示:Tocreateanewmock,theexistingstaticmockregistrationmustbederegistered  2、原因分析由提示信息可知,静态模拟已经注册过了,再次注册时必须先将之前的撤销。所以我们要撤销之前的注册信息,再执行。这里提供另一种方法,将模拟静态的方法......
  • getchar和putchar
    在接受单个字符和打印单个字符时,可以使用getchar和putchar。getchar()getchar()函数返回⽤⼾从键盘输⼊的⼀个字符,使⽤时不带有任何参数,等同于使⽤scanf()⽅法读取⼀个字符,它的原型定义在头文件<stdio.h>。getchar()不会忽略起⾸的空⽩字符,总是返回当前读取的第⼀个字符......
  • scanf函数
    基本用法用于读取用户的键盘输入,原型定义在头文件stdio.h。scanf()的第一个参数是格式字符串,里面会放置占位符,告诉编译器即将提取是数据类型,与printf()的占位符基本一致。其余参数用于存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。#include<stdio.h>intm......
  • pick这4款视频剪辑免费软件,批量剪辑不加班
    现在视频特别流行,不管是为了娱乐还是工作,视频剪辑都变得非常重要。但是找一款免费又好用,还能批量处理多个视频的软件挺不容易的。今天我就给大家推荐几款不错的视频剪辑免费软件。这些软件功能都很强大,剪辑也很方便,能帮你节省很多时间和精力。1.福昕视频工作室传送门✈ ht......
  • 盘点2024年让互联网人打Call的录屏大师,你种草了吗?
    嘿,朋友们,你们有没有为录个教程、直播回放或者游戏精彩瞬间而烦恼过?市面上录屏软件一大堆,但真正能让你录得开心、录出新高度的软件可不好找!今天我这个录屏大师就来给你们介绍2024年三款超棒的录屏神器,让你的录屏过程变得既有趣又轻松!一:Foxit专业录屏武器即时通道___ https:/......
  • VisionPro二次开发学习笔记13-使用CogToolBlock进行图像交互
    该程序演示了如何使用CogToolBlock进行图像交互.从vpp文件中加载一个ToolBlock。用户可以通过应用程序窗体上的数字增减控件修改ToolBlock输入端子的值。用户还可以从coins.idb或采集FIFO中选择图像。“运行一次”按钮执行以下操作:获取下一个图像或读取下一个图像......
  • PbootCMS上传图片失败或提示:未知错误
    1、空间是否满,是否有权限2、切换一下php版本,用php7.0试试3、用最新的版本替换掉ueditor所有文件PbootCMS-V3.1.3版本后台正常使用,但是编辑器上传图片一直显示无法成功,今天就来处理这个问题。问题:1:单图片上传按钮点击没反应或上传后一直无法成功。2:多图片上传显示后台配置项......