Web开发:ORM框架之使用Freesql的DbFrist封装常见工具

一、调用

public class Program
{

    static string connectionstring  = "连接字符串(数据库名)";
    static void Main(string[] args)
    {
        //1.连接数据库
        var freesql = new FreeSqlBuilder()
                    .UseConnectionString(DataType.SqlServer, connectionstring)//连接数据库
                    //.UseMonitorCommand(cmd => Console.Write(cmd.CommandText))//打印SQL
                    .Build();

        //2.数据库=>C#实体
            List<string> tablenames = new List<string> { {"数据表1"} , {"数据表2"} };
            string entitystring = GetEntitystring(freesql,tablenames);
            Console.WriteLine(entitystring);
    }

}

二、基础功能封装

public class CsProperty
{
    /// <summary>
    /// 字段名称(例如Id)
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// Cs默认值(例如DateTime.Now true/false)
    /// </summary>
    public string CsDefaultValue { get; set; }
    /// <summary>
    /// 数据库默认值(例如'2027-01-01' 1/0)
    /// </summary>
    public string DefaultValue { get; set; }
    /// <summary>
    /// cs类型(例如int?)
    /// </summary>
    public string CsType { get; set; }
    /// <summary>
    /// 字段注释
    /// </summary>
    public string Comment { get; set; }
    /// <summary>
    /// 字段是否可空
    /// </summary>
    public bool IsNullable { get; set; }
    /// <summary>
    /// 是否主键(不支持Doris)
    /// </summary>
    public bool IsPrimaryKey { get; set; }
    /// <summary>
    /// 是否自增(不支持Doris)
    /// </summary>
    public bool IsIdentity { get; set; }
    /// <summary>
    /// 属性模板(例如 public int Id { get; set; } )
    /// </summary>
    public string Property { get; set; }
 
}
 
public static class Logical
{
 
    /// <summary>
    /// 生成实体类的方法
    /// </summary>
    public static string GetEntityGrammar(IFreeSql freesql, List<string> tablenames)
    {
        string output = "";
        foreach (var tablename in tablenames)
        {
            var tableInfo = freesql.DbFirst.GetTableByName(tablename);
            var tableComment = tableInfo.Comment;
            var summaryTableComment = string.IsNullOrEmpty(tableComment) ? "" : $"/// <summary>\n///  {tableComment}\n/// </summary>\n";
            string result = $"{summaryTableComment}[Table(\"{tablename}\")]\npublic class {ConvertToPascalCase(tablename)}  \n{{\n\n";
            var CSList = ChangeCsType(tableInfo.Columns.OrderBy(x => x.Position).ToList());
            foreach (var item in CSList)
            {
                string feild = "";
                string itemNameLow = item.Name.ToString().ToLower();
                if (!string.IsNullOrWhiteSpace(item.Comment))
                {
                    feild += $"\t/// <summary>\n\t///  {item.Comment}\n\t/// </summary>\n";
                    feild += $"\t[Description(\"{item.Comment}\")]\n";
                }
                if (item.IsIdentity || itemNameLow.Equals("id"))
                {
                    string addKey = item.IsPrimaryKey ? "IsPrimary = true," : "";
                    feild += $"\t[FreeSql.DataAnnotations.Column({addKey}IsIdentity = true,Name =\"{item.Name}\")]\n";
                }
                else if (!item.IsIdentity && item.IsPrimaryKey)
                {
                    feild += $"\t[FreeSql.DataAnnotations.Column(IsPrimary = true,Name =\"{item.Name}\")]\n";
                }
                else
                {
                    if (itemNameLow.Equals("createtime"))
                    {
                        feild += $"\t[FreeSql.DataAnnotations.Column(ServerTime = DateTimeKind.Local, CanUpdate = false,Name = \"{item.Name}\")]\n";
                    }
                    else if (itemNameLow.Equals("createuser"))
                    {
                        feild += $"\t[FreeSql.DataAnnotations.Column(CanUpdate = false, Name = \"{item.Name}\")]\n";
                    }
                    else if (itemNameLow.Equals("updatetime"))
                    {
                        var isNull = item.IsNullable ? "CanInsert = false," : "";
                        feild += $"\t[FreeSql.DataAnnotations.Column(ServerTime = DateTimeKind.Local,{isNull}Name = \"{item.Name}\")]\n";
                    }
                    else
                    {
                        feild += $"\t[Column(\"{item.Name}\")]\n";
                    }
                }
                feild += $"\tpublic {item.CsType} {GetFormatName(item.Name)} {{ get; set; }}\n\n";
                result += feild;
            }
            result += "}";
            output += result + "\n";
        }
        return output;
    }
 
    /// <summary>
    /// 生成实体类Dto的方法(最后两个入参是前缀和后缀)
    /// </summary>
    public static string GetDtoGrammar(IFreeSql freesql, List<string> tablenames, string prefix = "", string suffix = "Dto")
    {
        string output = "";
        foreach (var tablename in tablenames)
        {
            var tableInfo = freesql.DbFirst.GetTableByName(tablename);
            var tableComment = tableInfo.Comment;
            var summaryTableComment = string.IsNullOrEmpty(tableComment) ? "" : $"/// <summary>\n///  {tableComment}(Dto)\n/// </summary>";
            string result = $"{summaryTableComment}\npublic class {prefix}{ConvertToPascalCase(tablename)}{suffix}  \n{{\n\n";
            var CSList = ChangeCsType(tableInfo.Columns.OrderBy(x => x.Position).ToList());
            foreach (var item in CSList)
            {
                string feild = "";
                string itemNameLow = item.Name.ToString().ToLower();
                if (!string.IsNullOrWhiteSpace(item.Comment))
                {
                    feild += $"\t/// <summary>\n\t///  {item.Comment}\n\t/// </summary>\n";
                }
                feild += $"\tpublic {item.CsType} {GetFormatName(item.Name)} {{ get; set; }}\n\n";
                result += feild;
            }
            result += "}";
            output += result + "\n";
        }
        return output;
    }
 
    /// <summary>
    /// 生成创建实体的方法
    /// </summary>
    public static string GetBuildEntity(IFreeSql freesql, List<string> tablenames)
    {
        if (tablenames.Count == 0)
        {
            return null;
        }
        string output = "";
        StringBuilder sb_en = new StringBuilder();
        StringBuilder sb_lt = new StringBuilder();
        foreach (var tablename in tablenames)
        {
 
            var tableInfo = freesql.DbFirst.GetTableByName(tablename);
            var tablelist = ChangeCsType(tableInfo.Columns.ToList());
            var first = TryGetFirstDbValue(freesql, tablename);
            var showtablename = tablename.Replace("_", "");
            sb_en.Append($"var {showtablename} = new {ConvertToPascalCase(tablename)}\n{{\n");
            sb_lt.Append($"var destictlist = new List<{ConvertToPascalCase(tablename)}>();\n");
            sb_lt.Append($"var sourcelist = new List<{ConvertToPascalCase(tablename)}>();\n");
            sb_lt.Append($"foreach (var item in sourcelist)\n{{\n");
            sb_lt.Append($"\tvar entity = new {ConvertToPascalCase(tablename)}();\n");
            int index = 0;
            foreach (var item in tablelist)
            {
                bool isLast = index == tablelist.Count - 1;
                var value = (first == null ? item.CsDefaultValue : first[item.Name]);
                if (new List<string>() { "int", "decimal", "int?", "decimal?", "double", "double?" }.Contains(item.CsType.ToLower()))
                {
                    value = $"{value}{(item.CsType.ToLower().Contains("decimal") ? "m" : "")}";
                }
                else if (item.CsType.ToLower().Contains("time"))
                {
                    value = $"{(string.IsNullOrEmpty(value) ? "null" : $"DateTime.Parse(\"{value}\")")}";
                }
                else//字符串系列
                {
                    value = $"\"{value}\"";
                }
                item.Name = GetFormatName(item.Name);
                if (isLast)
                {
                    sb_en.Append($"\t{item.Name} = {value}\n");
                }
                else
                {
                    sb_en.Append($"\t{item.Name} = {value},\n");
                }
                sb_lt.Append($"\tentity.{item.Name} = item.{item.Name};\n");
                index++;
            }
            sb_en.Append($"}};\n");
            sb_lt.Append($"\tdestictlist.Add(entity);\n}}");
        }
        output = sb_en.ToString() + "\n\n" + sb_lt.ToString();
        return output;
    }
 
    /// <summary>
    /// 获取这个表的第一条的内容字典(key:value=字段:内容)
    /// </summary>
    /// <returns></returns>
    public static Dictionary<string, string> TryGetFirstDbValue(IFreeSql freeSql, string tablename)
    {
        var res = freeSql.Select<object>().AsTable((old, news) => tablename).Take(1).ToDataTable();
        if (res.Rows.Count > 0)
        {
            //有数据的
 
            // 初始化一个字典,用来存放字段:值
            Dictionary<string, string> dataDict = new Dictionary<string, string>();
            // 取第一行数据
            var dataRow = res.Rows[0];
            // 遍历每一列,列名为键,列值为值
            foreach (DataColumn column in res.Columns)
            {
                dataDict[column.ColumnName] = dataRow[column].ToString();  // 将列名和对应的值放入字典
            }
            return dataDict;
        }
        return null;
    }
 
    /// <summary>
    /// 根据表名获取表的详细信息
    /// </summary>
    public static List<string> GetTableDetails(IFreeSql freesql, List<string> tablenames)
    {
        List<string> result = new List<string>();
 
        foreach (var tablename in tablenames)
        {
            var detail = freesql.DbFirst.GetTableByName(tablename);
            int index = 0;
            List<string> res = new List<string>();
 
            foreach (var item in detail.Indexes)
            {
                index++;
                string indexcontent = "";
                foreach (var jtem in item.Columns)
                {
                    indexcontent += jtem?.Column?.Name + ",";
                }
                res.Add(indexcontent.Trim(','));
            }
 
            // 每个信息单独作为一个 string
            result.Add($"表名称: {detail.Name}");
            result.Add($"表注释: {(string.IsNullOrEmpty(detail?.Comment) ? "无表注释" : detail?.Comment)}");
            result.Add($"表主键: {detail?.Primarys.FirstOrDefault()?.Name ?? "无表主键"}");
            result.Add($"表的自增列: {detail?.Identitys.FirstOrDefault()?.Name ?? "无自增列"}");
            result.Add($"表的字段数: {detail.Columns.Count}");
            result.Add($"表的索引数: {detail.Indexes.Count} ({string.Join(",", res)})");
        }
        return result;
    }
 
    /// <summary>
    /// 随机插入数据
    /// </summary>
    public static string InsertRandomData(IFreeSql freesql, List<string> tablenamelist, int count)
    {
        foreach (var tablename in tablenamelist)
        {
            // 获取表的结构信息
            var tableInfo = freesql.DbFirst.GetTableByName(tablename);
 
            // 构建字段名和占位符
            var fieldNames = string.Join(",", tableInfo.Columns.Where(x => !x.IsIdentity).OrderBy(x => x.Position).Select(c => c.Name));
            var valuesBuilder = new StringBuilder();
 
            // 随机数生成器
            Random random = new Random();
 
            // 执行插入
            for (int i = 0; i < count; i++)
            {
                StringBuilder valueBuilder = new StringBuilder();
 
                foreach (var item in tableInfo.Columns.Where(x => !x.IsIdentity).OrderBy(x => x.Position))
                {
                    var cstype = item.CsType.Name.ToLower();
                    object defaultValue = null;
                    if (cstype.Equals("string"))
                    {
                        defaultValue = item.MaxLength <= 20 ? $"数据{i}" : $"模拟测试数据{i}";
                    }
                    else if (cstype.StartsWith("int") || cstype.StartsWith("decimal"))
                    {
                        defaultValue = random.Next(0, 1000); // 随机整数
                    }
                    else if (cstype.Equals("datetime"))
                    {
                        defaultValue = DateTime.Now.AddDays(random.Next(-30, 0)); // 随机日期
                    }
                    else if (cstype.Equals("boolean"))
                    {
                        defaultValue = random.Next(0, 2) == 1; // 随机布尔值
                    }
                    else
                    {
                        defaultValue = DBNull.Value; // 未处理的其他类型
                    }
 
                    // 处理值为 null 或 DBNull 的情况
                    if (defaultValue == null || defaultValue == DBNull.Value)
                    {
                        valueBuilder.Append("NULL,");
                    }
                    else if (cstype.Equals("string"))
                    {
                        valueBuilder.Append($"'{defaultValue}',");
                    }
                    else if (cstype.Equals("datetime"))
                    {
                        valueBuilder.Append($"'{((DateTime)defaultValue):yyyy-MM-dd HH:mm:ss}',");
                    }
                    else
                    {
                        valueBuilder.Append($"{defaultValue},");
                    }
                }
 
                // 去掉最后一个逗号
                valueBuilder.Length--;
 
                // 构建完整的 SQL 插入语句
                string insertSql = $"INSERT INTO {tablename} ({fieldNames}) VALUES ({valueBuilder})";
 
                // 执行插入操作
                var effectcount = freesql.Ado.ExecuteNonQuery(insertSql);
 
            }
 
        }
        return $"执行插入到表【{string.Join(",", tablenamelist)}】成功!各自插入了【{count}】条数据!";
    }
 
    /// <summary>
    /// 将列转化为Cs类型表达式
    /// </summary>
    public static List<CsProperty> ChangeCsType(List<DbColumnInfo> list)
    {
        List<CsProperty> result = new List<CsProperty>();
        foreach (var item in list.OrderBy(x => x.Position))
        {
            CsProperty en = new CsProperty();
            en.Name = item.Name;
            en.Comment = item.Comment;
            en.CsDefaultValue = item.DefaultValue;
            en.DefaultValue = item.DefaultValue;
            en.IsNullable = item.IsNullable;
            en.IsIdentity = item.IsIdentity;
            en.IsPrimaryKey = item.IsPrimary;
            var cstype = item.CsType.Name.ToString().ToLower();
            var random = new Random();
            var rnum = random.Next(0, 9999);
 
            if (cstype.Equals("string"))
            {
                en.CsDefaultValue = item.MaxLength <= 10 ? $"\"默认值\"" : $"\"默认值数据{rnum}\"";
                en.DefaultValue = "测试";
                en.CsType = "string";
            }
 
            else if (cstype.StartsWith("int"))
            {
                en.CsDefaultValue = rnum.ToString();
                en.DefaultValue = rnum.ToString();
                en.CsType = "int" + $"{(item.IsNullable ? "?" : "")}";
            }
            else if (cstype.StartsWith("decimal"))
            {
                en.CsDefaultValue = rnum.ToString();
                en.DefaultValue = rnum.ToString();
                en.CsType = "decimal" + $"{(item.IsNullable ? "?" : "")}";
            }
            else if (cstype.StartsWith("double") || cstype.StartsWith("single"))
            {
                en.CsDefaultValue = rnum.ToString();
                en.DefaultValue = rnum.ToString();
                en.CsType = "double" + $"{(item.IsNullable ? "?" : "")}";
            }
            else if (cstype.Equals("datetime"))
            {
                en.CsDefaultValue = "DateTime.Now"; //  今天日期
                en.DefaultValue = DateTime.Now.Date.ToString(); //  今天日期
                en.CsType = "DateTime" + $"{(item.IsNullable ? "?" : "")}";
            }
            else if (cstype.Equals("boolean"))
            {
                en.CsDefaultValue = (random.Next(0, 2) == 1).ToString(); // 随机布尔值
                en.DefaultValue = random.Next(0, 1).ToString(); // 随机0 1
                en.CsType = "bool";
            }
            else
            {
                en.CsDefaultValue = "未知";
                en.DefaultValue = "未知";
                en.CsType = item.CsType.Name.ToLower();
            }
            en.Property = $"public {en.CsType} {en.Name} {{ get; set; }}";
            result.Add(en);
        }
        return result;
    }
 
    /// <summary>
    /// 将列转化为Cs类型表达式
    /// </summary>
    public static string ChangeCsType(string data)
    {
        var cstype = data.ToLower();
        if (cstype.Contains("system."))
        {
            cstype = cstype.Split("system.")[1];
        }
        var result = "";
        if (cstype.Equals("string"))
        {
            result = "string";
        }
 
        else if (cstype.StartsWith("int"))
        {
            result = "int";
        }
        else if (cstype.StartsWith("decimal"))
        {
            result = "decimal;";
        }
        else if (cstype.StartsWith("double") || cstype.StartsWith("single"))
        {
            result = "double";
        }
        else if (cstype.Equals("datetime"))
        {
            result = "DateTime";
        }
        else if (cstype.Equals("boolean"))
        {
            result = "bool";
        }
        else
        {
            result = "string";
        }
        return result;
    }


        /// <summary>
        /// 输入查询SQL:输出查询SQL结果的插入语法(有字段限定、内容限定)
        /// </summary>
        /// <returns></returns>
        public static string GetInsertSQLBySQL(IFreeSql freesql, string sql, string tablename = "YourTableName")
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                var table = freesql.Select<object>().WithSql(sql).ToDataTable();
                var nameTypeList = table.Columns.Cast<DataColumn>().Select(x=> new { ColumnName=x.ColumnName, DataType=x.DataType.ToString(), AllowDBNull = x.AllowDBNull }).ToList();
                List<string> FeildNames = nameTypeList.Select(x=>x.ColumnName).ToList();
                List<string> ColumnsList = new List<string>();
                var FeildCounts = table.Columns.Count;
                var DataCounts = table.Rows.Count;
                var Pages = (int)Math.Ceiling((double)DataCounts / 1000);
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    ColumnsList.Add(table.Columns[i].ColumnName);
                }

                // 遍历每一页,批量插入每1000条数据
                for (int page = 0; page < Pages; page++)
                {
                    // 计算当前页的起始和结束行数
                    int startRow = page * 1000;
                    int endRow = Math.Min((page + 1) * 1000, DataCounts);

                    // 构建每一页的INSERT语句
                    var valuesList = new List<string>();
                    for (int i = startRow; i < endRow; i++)
                    {
                        var values = new List<string>();
                        for (int j = 0; j < FeildCounts; j++)
                        {
                            var feildName = FeildNames[j];
                            var feildType = nameTypeList.FirstOrDefault(x=>x.ColumnName==feildName).DataType.Split(".")[1].ToLower();
                            var allowNull = nameTypeList.FirstOrDefault(x => x.ColumnName == feildName).AllowDBNull;
                            var value = table.Rows[i][j].ToString();
                            if (new List<string> { "int32", "int64", "decimal", "double" }.Contains(feildType.ToLower()))
                            {
                                string ins = value;
                                if (string.IsNullOrWhiteSpace(value))
                                {
                                    ins = allowNull ? "NULL" : "0";
                                }
                                values.Add($"{ins}");//两边不加引号,默认值是0
                            }
                            else if (new List<string> { "boolean" }.Contains(feildType.ToLower()))
                            {
                                values.Add($"{(value.ToLower().Equals("true") ? 1 : 0)}");
                            }
                            else
                            {
                                var svalue = table.Rows[i][j];
                                if (svalue == DBNull.Value)
                                {
                                    values.Add($"NULL");
                                }
                                else if(svalue.ToString() == "")
                                {
                                    values.Add($"''");
                                }
                                else
                                {
                                    values.Add($"'{value}'");
                                }
                            }

                        }
                        // 将当前行的值加到valuesList中
                        valuesList.Add($"({string.Join(", ", values)})");
                    }

                    // 生成INSERT语句,并加到StringBuilder中
                    sb.AppendLine($"INSERT INTO {tablename} ({string.Join(", ", ColumnsList)})\nVALUES \n{string.Join(",\n", valuesList)};");
                }


                return sb.ToString();
            }
            catch (Exception ex)
            {
                return $"出错了:{ex.Message.ToString()}";
            }

        }
 
    /// <summary>
    /// 输入表名,输出Crud语法
    /// </summary>
    /// <returns></returns>
    public static string GetCrudByTableName(IFreeSql freesql, List<string> tablenamelist)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var table in tablenamelist)
        {
            var dbinfo = freesql.DbFirst.GetTableByName(table);
            var ColumnsList = dbinfo.Columns.OrderBy(x => x.Position).Select(x => x.Name).ToList();
            var key = dbinfo.Primarys.FirstOrDefault()?.Name ?? "Id";
            sb.AppendLine($"SELECT \n\t{string.Join(",\n\t", ColumnsList)} \nFROM \t{table}\n");
            sb.AppendLine($"SELECT * INTO 新表名 FROM {table}; -- 迁移表结构和数据,仅支持sqlserver\n");
            sb.AppendLine($"INSERT INTO {table} ({string.Join("\n\t,", ColumnsList)}) \nVALUES \n()\n");
            sb.AppendLine($"DELETE FROM {table} WHERE {key} IN ()\n");
            sb.AppendLine($"UPDATE {table} SET xxx=xxx WHERE {key} IN ()\n");
        }
        return sb.ToString();
    }
 
    /// <summary>
    /// 根据查询SQL输出实体(一般用于联表,不要传入ORDERBY)
    /// </summary>
    public static string GetEntityBySQL(IFreeSql freesql, string sql)
    {
        StringBuilder sb = new StringBuilder();
        var dt = freesql.Select<object>().WithSql(sql).ToDataTable();
        sb.AppendLine($"\npublic class Model\n{{\n");
        // 获取并打印每个列的类型
        foreach (DataColumn column in dt.Columns)
        {//ChangeCsType
            sb.AppendLine($"\tpublic {ChangeCsType(column.DataType.Name.ToString())} {column.ColumnName} {{ get; set; }}");
        }
        sb.AppendLine($"\n}}");
        return sb.ToString();
    }
 
    #region 字段格式化
    //转化词(首字母大写)
    public static List<string> KeyWordsUpFirst = new List<string> { "code", "name", "value", "time", "state", "path", "point", "type", "mark", "user", "log", "status", "data", "flag", "pollutant", "url", "date", "speed", "direct", "rank", "order", "district", "town", "city", "key", "hour" };
 
 
    //转化词(全大写)
    public static List<string> KeyWordsAllUp = new List<string> { "aqi", "pm", "no", "so", "co", "tsi" };
 
    //最后替换字典(用key替代value)
    public static Dictionary<string, string> ReplaceDict = new Dictionary<string, string>()
    {
        {"Reason","ReaSOn" },{"Update","UpDate" },{"Normal","NOrmal"},{ "Remark","ReMark"},{ "Json","JSOn"}
    };
 
    //下划线转大驼峰
    public static string ConvertToPascalCase(string input)
    {
        // 分割字符串
        string[] words = input.Split('_');
 
        // 将每个单词的首字母大写并连接
        for (int i = 0; i < words.Length; i++)
        {
            if (words[i].Length > 0)
            {
                words[i] = char.ToUpper(words[i][0]) + words[i].Substring(1);
            }
        }
 
        // 返回连接后的结果
        return string.Join(string.Empty, words);
    }
 
    //首字母大写
    public static string CapitalizeFirstLetter(string str)
    {
        if (string.IsNullOrEmpty(str))
            return str; // 返回原始字符串,或可以返回空字符串
 
        return char.ToUpper(str[0]) + str.Substring(1);
    }
 
    /// <summary>
    /// 格式化字段
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public static string GetFormatName(string name)
    {
        string result = name;
        foreach (var item in KeyWordsUpFirst)
        {
            result = result.Replace(item, CapitalizeFirstLetter(item));
        }
        foreach (var item in KeyWordsAllUp)
        {
            result = result.Replace(item, item.ToUpper());
        }
        foreach (var item in ReplaceDict)
        {
            result = result.Replace(item.Value, item.Key);
        }
        result = ConvertToPascalCase(CapitalizeFirstLetter(result));
        return result;
    }
    #endregion
 
}

三、额外功能封装

1.通过Guid判断表关系

#region 求表关系(仅支持Guid类型)
public class TableRelation
{
    public string TableName { get; set; }
    public List<FeildDetail> dList { get; set; } = new List<FeildDetail>();

}
public class FeildDetail
{
    public string FeildName { get; set; }
    public List<string> FeildContent { get; set; }
    public string FeildRelation { get; set; }
}
public static string GetTableRelationShip(IFreeSql freesql, List<string> tablenamelist)
{
    //对比的关系,例如A表-B表
    List<string> compare = new List<string>();
    // 使用两个嵌套循环来生成所有的两两组合
    for (int i = 0; i < tablenamelist.Count; i++)
    {
        for (int j = i + 1; j < tablenamelist.Count; j++)
        {
            compare.Add(tablenamelist[i] + "-" + tablenamelist[j]);
        }
    }

    //表名,字段名称,Guid字段内容,结论
    var resList = new List<TableRelation>();
    foreach (var tableName in tablenamelist)
    {
        string pa1 = tableName;
        var dt = freesql.Select<object>().AsTable((x, y) => tableName).Take(1).ToDataTable();
        var columnList = dt.Columns.Cast<DataColumn>().Where(x => Guid.TryParse(dt.Rows[0][x].ToString(), out var t1) && !new List<string> { "creat", "update" }.Contains(x.ColumnName.ToLower())).Select(x => x.ColumnName).ToList();
        if (!columnList.Any())
        {
            return $"{tableName}未匹配到Guid类型,校验失败!";
        }
        List<FeildDetail> tlist = new List<FeildDetail>();
        foreach (var item in columnList)
        {
            var cName = item;
            dt = freesql.Select<object>().AsTable((x, y) => tableName).OrderBy(cName).Take(1000).ToDataTable();
            List<string> content = DtToDictionaryList(dt).Where(x => x.FieldName.Equals(cName)).Select(x => x.FieldValue).ToList();
            bool isUnique = content.Count == content.Distinct().Count();
            tlist.Add(new FeildDetail
            {
                FeildName = cName,
                FeildContent = content,
                FeildRelation = isUnique ? "一" : "多"
            });
        }
        resList.Add(new TableRelation
        {
            TableName = tableName,
            dList = tlist
        });
    }

    StringBuilder sb = new StringBuilder();
    foreach (var item in compare)
    {
        var left = resList.FirstOrDefault(x => x.TableName.Equals(item.Split('-')[0]));//A表
        var right = resList.FirstOrDefault(x => x.TableName.Equals(item.Split('-')[1]));//B表
        bool flag = false;
        foreach (var j in left.dList)
        {
            foreach (var k in right.dList)
            {
                bool isrealate = j.FeildContent.Intersect(k.FeildContent).Any();//存在交集
                if (isrealate)
                {
                    sb.AppendLine($"{item.Replace("-", "和")}之间的关系是:{j.FeildRelation}对{k.FeildRelation},通过【{j.FeildName}-{k.FeildName}】关联");
                    flag = true;
                    break;
                }
            }
        }
        if (!flag)
        {
            sb.AppendLine($"{item.Replace("-", "和")}之间的关系是:暂无关联关系");
        }
    }

    sb.AppendLine("————————————————————————————————");
    foreach (var item in resList)
    {
        var r = item.dList.Select(x => x.FeildName + ":" + (x.FeildRelation.Equals("一") ? "主键" : "关联键"));
        sb.AppendLine($"【表名】{item.TableName}【Guid字段和关系】{string.Join(",", r)}");
    }
    return sb.ToString();
}

// 返回每个列名、列类型和列值的元组列表
public static List<(string FieldName, string FieldType, string FieldValue)> DtToDictionaryList(DataTable res)
{
    var list = new List<(string FieldName, string FieldType, string FieldValue)>();

    // 遍历每行数据
    foreach (DataRow row in res.Rows)
    {
        // 遍历每列,获取字段名称、字段类型和字段值
        foreach (DataColumn column in res.Columns)
        {
            var fieldName = column.ColumnName;
            var fieldType = column.DataType.ToString();
            var fieldValue = row[column].ToString();

            // 添加元组到列表
            list.Add((fieldName, fieldType, fieldValue));
        }
    }

    return list;
}
#endregion

2.生成联表字段

/// <summary>
/// 输入表名,输出SELECT .... FROM A LEFT JOIN B ... 的语法
/// 处理字段重复有两种模式,模式1:字段重复则字段后面加字母,模式2:不允许重复,以第一张表出现的为准
/// </summary>
/// <param name="freesql"></param>
/// <param name="tableNames"></param>
/// <param name="notRepeat"></param>
/// <returns></returns>
public static string GetJoinSQLByTableNameList(IFreeSql freesql, List<string> tableNames ,int mode = 1)
{
    int id = 1;
    int id2 = 1;
    var cols = new List<string>();
    var allfeilds = new List<string>();
    StringBuilder sb = new StringBuilder();
    foreach (var item in tableNames)
    {
        var myCols = freesql.DbFirst.GetTableByName(item).Columns.OrderBy(x => x.Position).Select(x => x.Name);
        var myLab = (char)('A' + id - 1);
        foreach (var j in myCols)
        {
            if (cols.Exists(x => x == j))
            {
                if (mode == 2)
                {
                    continue;//不允许重复,就不加了,以第一个出现的为准
                }
                allfeilds.Add($"\t{myLab}.{j} AS {j}{myLab},\n");
            }
            else
            {
                allfeilds.Add($"\t{myLab}.{j} AS {j},\n");
            }
        }
        cols.AddRange(myCols);
        id++;
    }
    sb.Append(@$"SELECT 
{string.Join("", allfeilds).TrimEnd().TrimEnd(',')}
FROM {tableNames[0]} A
");
    foreach (var item in tableNames.Skip(1))
    {
        var myLab = (char)('A' + id2);
        sb.AppendLine(@$"LEFT JOIN {item} {myLab} ON 条件");
        id2++;
    }
    var res = sb.ToString();
    Console.WriteLine(res);
    return res;
}

3.模糊匹配单表全字段

#region 输出全字段模糊查找
public static string GetAllFeildsFuzzySearch(IFreeSql freesql,string tableName,string search)
{
    var allCols = freesql.DbFirst.GetTableByName(tableName).Columns.Select(x=>x.Name).ToList();
    StringBuilder sb = new StringBuilder($"SELECT * FROM {tableName}\n WHERE");
    foreach (var item in allCols)
    {
        var OR = allCols.IndexOf(item)==0 ? "\n" : "OR ";
        sb.AppendLine($"{OR}{item} like '%{search}%'");
    }
    Console.WriteLine(sb.ToString());
    return sb.ToString();
}
#endregion

4.根据Guid的值查找它在哪张表出现过

#region 根据Guid查找它在哪张表出现过
        /// <summary>
        /// 根据Guid查找它在哪张表出现过
        /// </summary>
        /// <param name="freesql"></param>
        /// <param name="guid"></param>
        /// <param name="type">1 sqlserver 2mysql</param>
        /// <returns></returns>
        public static string GetTableByGuidValue(IFreeSql freesql, string guid,int type = 1)
        {
            StringBuilder sb = new StringBuilder();
            int id = 1;
            string sql = @"SELECT DISTINCT A.TABLE_NAME, A.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS A
INNER JOIN INFORMATION_SCHEMA.TABLES B ON A.TABLE_NAME = B.TABLE_NAME
INNER JOIN sys.dm_db_partition_stats P ON OBJECT_ID(A.TABLE_NAME) = P.object_id
WHERE LOWER(A.COLUMN_NAME) LIKE '%id%' 
  AND LOWER(A.DATA_TYPE) LIKE '%char%' 
  AND B.TABLE_TYPE = 'BASE TABLE'
  AND P.index_id <= 1 
  AND P.row_count > 0 ";
            string sqlAdd = type == 1 ? @" OPTION (MAXDOP 1)" : "";//sqlserver查询需要阻止并行
            if (type == 2)
            {
                sql = @"select 
DISTINCT A.TABLE_NAME,A.COLUMN_NAME
from information_schema.columns  A
INNER JOIN (select * from information_schema.tables where TABLE_ROWS !=0 and TABLE_SCHEMA = (SELECT DATABASE()) ) B
ON A.TABLE_NAME = B.TABLE_NAME
where LOWER(column_name) like '%id%' AND LOWER(COLUMN_TYPE) LIKE '%char%'
ORDER BY A.TABLE_NAME";
            }
            var list = freesql.Select<object>().WithSql(sql).ToList<(string TableName,string FeildName)>();
            foreach (var item in list.GroupBy(x=>x.TableName))
            {
                var feilds = item.Select(x=>x.FeildName + $"='{guid}'").ToList();
                var condition = string.Join(" OR ", feilds);
                var check = freesql.Ado.Query<string>($"SELECT COUNT(1) AS TotalCount FROM {item.Key} WHERE {condition}{sqlAdd}").FirstOrDefault() != "0";
                if (check)
                {
                    foreach (var j in item)
                    {
                        var checkssql = $"SELECT COUNT(1) AS TotalCount FROM {item.Key} WHERE {j.FeildName} = '{guid}'";
                        var checkFeilds = freesql.Select<object>().WithSql(checkssql).ToList<string>().FirstOrDefault() != "0";
                        if (checkFeilds)
                        {
                            sb.AppendLine($"{id}.表【{item.Key}】-字段【{j.FeildName}】存在该值,参考SQL【{checkssql.Replace("COUNT(1) AS TotalCount", "*")}】");
                            id++;
                        }
                    }
                }
            }
            var res = sb.ToString();
            res = string.IsNullOrEmpty(res) ? "查找完毕,该数据库中所有表所有名称含id的字段(string类型)都未找到该值!" : res;
            Console.WriteLine(res);
            return res;
        }
        #endregion

5.获取表字段关系

#region 获取表字段关系
public static string GetTableFeildRelations(IFreeSql freesql, string table1,string table2)
{
    var col1 = freesql.DbFirst.GetTableByName(table1).Columns.OrderBy(x=>x.Position).Select(x=>x.Name);
    var col2 = freesql.DbFirst.GetTableByName(table2).Columns.OrderBy(x => x.Position).Select(x => x.Name);
    //共有
    var intersect = col1.Intersect(col2);
    var c1 = col1.Except(col2);
    var c2 = col2.Except(col1);
    StringBuilder sb = new StringBuilder();
    sb.AppendLine($"1.两表共有字段({intersect.Count()}/{col1.Count()+ col2.Count()}个)\n{string.Join("\n",intersect)}\n");
    sb.AppendLine($"2.【{table1}】表独有字段({c1.Count()}/{col1.Count()}个)\n{string.Join("\n", c1)}\n");
    sb.AppendLine($"3.【{table2}】表独有字段({c2.Count()}/{col2.Count()}个)\n{string.Join("\n", c2)}\n");
    var res = sb.ToString();
    Console.WriteLine(res);
    return res;
}
#endregion

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值