草庐IT

开源项目:数据库表结构生成文档工具

IT技术分享社区 2023-05-27 原文

目录

一、软件介绍

二、技术框架

三、功能介绍

四、代码展示

1、获取数据库信息部分代码

2、导出Html文档代码

五、运行效果

六、项目开源地址


一、软件介绍

今天给大家分享我自己编写的数据库表结构文档生成工具,方便大家在实际开发当中,可以很方便导出业务系统的表结构,也可以作为项目验收文档中数据库设计文档使用。这样可以大大减少编写数据库表结构文档的时间,有需要的朋友欢迎下载或者沟通交流!

二、技术框架

  • 编程语言:C# ( Net Framework4.5.5)
  • 数据库技术框架:Dapper
  • 导出Word文档:NPOI
  • 访问方式:WinForm窗体应用程序,Windows操作系统可以直接运行

三、功能介绍

  • 支持SQLServer、MySQL(5.7、8.0)、SQLite 三种类型的数据,持续更新
  • 支持Word、Html、MarkDown 三种格式的导出
  • 导出内容包含数据表(字段详情、字段注释、长度、默认值等)、创建表脚本、视图及视图脚本、存储过程及脚本
  • 支持生成文档的同时直接打开文档
  • 支持数据库备份(目前只支持SQLServer导出bak备份文件)

四、代码展示

1、获取数据库信息部分代码

   /// <summary>
        /// 获取数据库字符串
        /// </summary>
        /// <param name="servername"></param>
        /// <param name="uid"></param>
        /// <param name="pwd"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public string GetConnectioning(string servername, string uid, string pwd, string db, string port)
        {
            return string.Format("server={0};uid={1};pwd={2};database={3}", servername, uid, pwd, db);
        }
        /// <summary>
        /// 获取数据库列表
        /// </summary>
        /// <param name="conStr"></param>
        /// <returns></returns>
        public List<string> GetDBNameList(string conStr)
        {
            //List<DBName> list =new List<DBName>();
            string sql = "select [name] from master.dbo.sysdatabases where DBId>6 Order By [Name] ";
            try
            {
                using (SqlConnection connection = new SqlConnection(conStr))
                {
                    var list = connection.Query<string>(sql).ToList();
                    return list;
                }
            }
            catch
            {
                return null;
            }

        }

        public List<DBModel> GetDBList(string conStr)
        {
            //List<DBName> list =new List<DBName>();
            string sql = "select [name] from master.dbo.sysdatabases where DBId>6 Order By [Name] ";
            try
            {
                using (SqlConnection connection = new SqlConnection(conStr))
                {
                    var list = connection.Query<DBModel>(sql).ToList();
                    return list;
                }
            }
            catch
            {
                return null;
            }

        }
        /// <summary>
        /// 获取特定数据库的表名列表
        /// </summary>
        /// <param name="conStr"></param>
        /// <returns></returns>

        public List<TableModel> GetDBTableList(string conStr, string dbName = "")
        {
            var list = new List<TableModel>();
            //string sql = "SELECT TABLE_NAME as name FROM INFORMATION_SCHEMA.TABLES where TABLE_TYPE='BASE TABLE' ";
            string sql = "select a.name AS tableName,CONVERT(NVARCHAR(100),isnull(g.[value],'')) AS tableDesc from sys.tables a left join sys.extended_properties g on (a.object_id = g.major_id AND g.minor_id = 0)";
            try
            {
                using (SqlConnection connection = new SqlConnection(conStr))
                {
                    list = connection.Query<TableModel>(sql).ToList();
                }
            }
            catch
            {

            }
            return list;
        }
        /// <summary>
        /// 获取特定数据库里面的存储过程
        /// </summary>
        /// <param name="conStr"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public List<ProcModel> GetProcList(string conStr, string dbName = "")
        {
            var list = new List<ProcModel>();
            string sql = @"  select name as procName, (select text from syscomments where id=OBJECT_ID(name)) as proDerails
                         from dbo.sysobjects  o  where OBJECTPROPERTY(id, N'IsProcedure') = 1 order by name  ";
            try
            {               
                using (SqlConnection connection = new SqlConnection(conStr))
                {
                    list = connection.Query<ProcModel>(sql).ToList();
                }
            }
            catch
            {

            }
            return list;
        }
        /// <summary>
        /// 获取特定数据库里面的视图
        /// </summary>
        /// <param name="conStr"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public List<ViewModel> GetViewList(string conStr, string dbName = "")
        {
            var list = new List<ViewModel>();
            string sql = @"  select name as viewName, (select text from syscomments where id=OBJECT_ID(name)) as viewDerails
                         from dbo.sysobjects  o  where OBJECTPROPERTY(id, N'IsView') = 1 order by name  ";
            try
            {              
                using (SqlConnection connection = new SqlConnection(conStr))
                {
                    list = connection.Query<ViewModel>(sql).ToList();
                }
            }
            catch
            {

            }
            return list;
        }

        /// <summary>
        /// 获取字段的信息
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="conStr"></param>
        /// <returns></returns>
        public List<TableDetail> GetTableDetail(string tableName, string conStr, string dbName = "")
        {
            var list = new List<TableDetail>();
            StringBuilder sb = new StringBuilder();
            sb.Append("SELECT [index] = a.colorder,    Title = a.name,    isMark =        CASE    WHEN COLUMNPROPERTY(a.id, a.name, 'IsIdentity') = 1 THEN '1' ELSE '0' END, ");
            sb.Append("isPK =  CASE   WHEN EXISTS(SELECT  1  FROM sysobjects WHERE xtype = 'PK' AND parent_obj = a.id AND name IN(SELECT name  FROM sysindexes WHERE indid IN(SELECT indid  FROM sysindexkeys  WHERE id = a.id AND colid = a.colid)) ) THEN '1' ELSE '0' END, ");
            sb.Append("	FieldType = b.name,fieldLenth = COLUMNPROPERTY(a.id, a.name, 'PRECISION'),isAllowEmpty =  CASE   WHEN a.isnullable = 1 THEN '1' ELSE '0' END, defaultValue = ISNULL(e.text, ''), fieldDesc = ISNULL(g.[value], '') ");
            sb.Append("FROM syscolumns a LEFT JOIN systypes b  ON a.xusertype = b.xusertype INNER JOIN sysobjects d ON a.id = d.id AND d.xtype = 'U' AND d.name <> 'dtproperties' LEFT JOIN syscomments e ON a.cdefault = e.id ");
            sb.Append("LEFT JOIN sys.extended_properties g ON a.id = G.major_id AND a.colid = g.minor_id LEFT JOIN sys.extended_properties f ON d.id = f.major_id AND f.minor_id = 0");
            //--如果只查询指定表,加上此红色where条件,tablename是要查询的表名;去除红色where条件查询说有的表信息
            sb.Append("WHERE d.name = '" + tableName + "' ORDER BY a.id, a.colorder, d.name");
            try
            {
                using (SqlConnection connection = new SqlConnection(conStr))
                {
                    list = connection.Query<TableDetail>(sb.ToString()).ToList();
                }
            }
            catch
            { }

            return list;
        }

2、导出Html文档代码

  /// <summary>
        /// 生成html文件
        /// </summary>
        /// <param name="list"></param>
        /// <param name="conStr"></param>
        /// <param name="db"></param>
        /// <param name="type"></param>
        public void CreateToHtml(List<TableModel> list, string conStr, string db, int type, List<string> checkList)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<html><meta charset=\"utf-8\" /><meta http-equiv = \"Content-Language\" content = \"zh-CN\" >");
            sb.Append("<head><title>数据库说明文档</title><body>");
            sb.Append("<style type=\"text/css\">\n");
            sb.Append("body { font-size: 9pt;}\n");
            sb.Append(".styledb { font-size: 14px; }\n");
            sb.Append(".styletab {font-size: 14px;padding-top: 15px; }\n</style></head><body>");
            sb.Append("<h1 style=\"text-align:center;\">" + db + "数据库说明文档</h1>");


            GetDBService(type);

            #region 创建一个表格
            if (checkList.Where(m => m.Equals("表")).Count() > 0)
            {
                sb.Append("<h2>一、表结构</h2>");
                sb.Append("");
                sb.Append("");
                if (list.Count > 0)
                {
                    foreach (var item in list)
                    {
                        if (item.tableDesc != null && item.tableDesc != "")
                        {
                            sb.Append("<h3>表名:" + item.tableName + "(" + item.tableDesc + ")</h3>");
                        }
                        else
                        {
                            sb.Append("<h3>表名:" + item.tableName + "</h3>");
                        }
                        sb.Append(" <table cellspacing=\"0\" cellpadding=\"5\" border=\"1\" width=\"100%\" bordercolorlight=\"#4F7FC9\" bordercolordark=\"#D3D8E0\">");
                        sb.Append("<thead bgcolor=\"#E3EFFF\"> <th>序号</th><th>字段名称</th><th>标识</th><th>主键</th><th>字段类型</th><th>字段长度</th><th>允许空值</th><th>字段默认值</th><th>字段备注</th></thead>");
                        sb.Append("<tbody>");
                        //从第二行开始 因为第一行是表头
                        int i = 1;
                        var tabledetaillist = service.GetTableDetail(item.tableName, conStr, db);


                        if (tabledetaillist != null && tabledetaillist.Count > 0)
                        {
                            foreach (var itm in tabledetaillist)
                            {
                                sb.Append("<tr>");
                                sb.Append("<td>" + itm.index + "</td>");
                                sb.Append("<td>" + itm.Title + "</td>");
                                sb.Append("<td>" + itm.isMark + "</td>");
                                sb.Append("<td>" + itm.isPK + "</td>");
                                sb.Append("<td>" + itm.FieldType + "</td>");
                                sb.Append("<td>" + itm.fieldLenth + "</td>");
                                sb.Append("<td>" + itm.isAllowEmpty + "</td>");
                                sb.Append("<td>" + itm.defaultValue + "</td>");
                                sb.Append("<td>" + itm.fieldDesc + "</td>");
                                sb.Append("</tr>");
                                i++;
                            }
                        }
                        sb.Append("</tbody></table>");

                        sb.Append("<h4>" + item.tableName + "建表脚本</h4><br/>");
                        sb.Append("<span>" + service.GetTableSQL(item.tableName, conStr) + "</span>");


                    }
                }
            }
            #endregion

            #region 存储过程
            if (checkList.Where(m => m.Equals("存储过程")).Count() > 0)
            {
                List<ProcModel> proclist = new List<ProcModel>();
                proclist = service.GetProcList(conStr, db);
                sb.Append("<h2>二、存储过程</h2>");
                if (proclist != null && proclist.Count > 0)
                {
                    foreach (var item in proclist)
                    {
                        sb.Append("<h3>存储过程名称:" + item.procName + "</h3>");
                        sb.Append("<span>" + item.proDerails + "</span>");
                    }
                }
            }
            #endregion

            #region 视图
            if (checkList.Where(m => m.Equals("视图")).Count() > 0)
            {
                List<ViewModel> viewlist = new List<ViewModel>();
                viewlist = service.GetViewList(conStr, db);
                sb.Append("<h2>三、视图</h2>");
                if (viewlist.Count > 0)
                {

                    foreach (var item in viewlist)
                    {
                        sb.Append("<h3>视图名称:" + item.viewName + "</h3>");
                        sb.Append("<span>" + item.viewDerails + "</span>");
                    }
                }
            }
            #endregion

            sb.Append("</body></html>");
            sb.ToString();
            string filename = db + "-数据库说明文档";//文件名
            SaveFileDialog saveDialog = new SaveFileDialog();
            saveDialog.DefaultExt = "html";
            saveDialog.Filter = "html文件|*.html";
            saveDialog.FileName = filename;
            saveDialog.ShowDialog();
            filename = saveDialog.FileName;
            if (filename.IndexOf(":") < 0) return; //被点了取消         
            StreamWriter sw1 = new StreamWriter(saveDialog.FileName, false);
            sw1.WriteLine(sb);
            sw1.Close();
            System.Diagnostics.Process.Start(filename);

        }

五、运行效果

应用程序主界面

支持三种生成文档类型:每次只能选择一种,推荐使用markdown格式

Word文档生成效果

Html文档生成效果

MarkDown文档效果

针对SQLServer数据库备份

​​​​​​​六、项目开源地址

GitHub:https://github.com/hgmsq/SqlToDocTool

Gitee:https://gitee.com/hgm1989/SqlToDocTool

Gitcode:https://gitcode.net/xishining/SqlToDocTool

有关开源项目:数据库表结构生成文档工具的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  6. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  7. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  8. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  9. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  10. ruby-on-rails - Ruby on Rails - 为文本区域和图片生成列 - 2

    我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数

随机推荐