小程序大智慧,sqlserver 注释提取工具

原文:小程序大智慧,sqlserver
注释提取工具

开篇背景


我习惯在写表的创建脚本时将注释直接写在脚本里,比如

?




/*账套*/

CREATE TABLE [dbo].[AccountingBook]

(

    [IDNO]          NVARCHAR (255) NOT
NULL,    /*ID*/

    [BH]            NVARCHAR (255) NULL,        /*业务编号*/

    [Name]          NVARCHAR (255) NOT
NULL,    /*名称*/

    [Decription]    NVARCHAR (255) NULL,        /*描述*/

    [Owner]         NVARCHAR (255) NOT
NULL,    /*所属*/

    CONSTRAINT
[PK_AccountingBook] PRIMARY
KEY CLUSTERED ([IDNO] ASC)

)

这样写很直观,如果在vs里创建一个数据库项目,把表的创建脚本放在里面进行管理,就非常方便的。

由于习惯用自己的Orm框架,所以DTO也就是那些数据映射实体我都是用codeSmith生成,生成这些DTO对象时,我想共用我的那些注释,那么我该怎么办呢,之前,我需要把这些注释复制出来写成一些注释创建的脚本,像这样  

?




exec sp_addextendedproperty N‘MS_Description‘, N‘字段描述‘, N‘user‘, N‘dbo‘, N‘table‘, N‘表名‘, N‘column‘, N‘字段名‘

添加注释的目的是除了在使用数据库连接工具时方便查看表和字段的说明外,还可以使用CodeSmith生成代码的时候就可以通过编写模版生成带注释的映射DTO
对象,如下  


/// <summary>
/// 业务编号
/// </summary>
[Column(ColumnName=Columns.BH,FullName=Columns.BHFullName,Index=1,CType=typeof(string),Description="业务编号")]
[DataMember(Order = 1)]
public virtual string BH{get;set;}

但是由于表创建脚本里的注释不能直接写入到数据库的表和字段中,所以注释的创建脚本我需要再写一次,我觉得比较不爽,于是我决定写个小工具从表的创建脚本里面抽取那些本来就写好的注释,从而减小重复机械的工作,也防止错误的发生。

这样一个程序非常简单,下面说一下思路

实现


一,写好带注释的表脚本,并提取这些信息

格式按文章开始讲到的那样写好,即"/*注释*/",“*”可以是多个,比如"/*********注释***********/",并将这些脚本存放到相同根目录

要提取这些注释,最大的功臣非正则表达式莫属了

    

a.提取表头的注释,也就是表名的解释正则表达式      

 private readonly Regex _tableReg = new Regex(@"/[\*]+([^\*]*)[\*]+/[\r\n\s]*CREATE TABLE \[dbo\].\[(\w*)\]");

b.提取列的注释正则表达式

private readonly Regex _columnsReg = new Regex(@"\[([\w]*)\][^\/]*/[\*]+([^\*]*)[\*]+/");

二,递归查找到这些表的创建脚本,将每个生成注释脚本的字符串连接起来


Func<string, List<string>> getFolderSqlNotes = null;
getFolderSqlNotes = path =>
{
var listAll = new List<string>();
var files = Directory.GetFiles(path);
var dirs = Directory.GetDirectories(path);
foreach (string t in dirs)
{
listAll.AddRange(getFolderSqlNotes(t)); ;
}
var listStr = files.Where(m => m.EndsWith(".sql")).Select(GetDescriptionSql).ToList();
listAll.AddRange(listStr);
return listAll;
};
var list = getFolderSqlNotes(Path);
return string.Join("\r\n", list);

三,执行生成好的脚本(如下图),注释创建完成

四,用codesimth 生成映射类(已带注释)

核心代码

 1 namespace GenrerateSqlDescription
2 {
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Linq;
7 using System.Text;
8 using System.Text.RegularExpressions;
9
10
11 public class SqlNotesGenerator
12 {
13 private readonly Regex _tableReg = new Regex(@"/[\*]+([^\*]*)[\*]+/[\r\n\s]*CREATE TABLE \[dbo\].\[(\w*)\]");
14 private readonly Regex _columnsReg = new Regex(@"\[([\w]*)\][^\/]*/[\*]+([^\*]*)[\*]+/");
15 private const string TableDescriptionCrateSqlFormat = "EXEC sp_addextendedproperty ‘MS_Description‘,‘{0}‘,‘user ‘,dbo,‘table‘,[{1}];\r\n";
16 private const string ColumnDescriptionCrateSqlFormat = "EXEC sp_addextendedproperty ‘MS_Description‘,‘{0}‘,‘user‘,dbo,‘table‘,[{1}],‘column‘,‘{2}‘;\r\n";
17 private const string TableDescriptionDropSqlFormat = "EXEC sp_dropextendedproperty ‘MS_Description‘,‘user‘,dbo,‘table‘,[{0}];\r\n";
18 private const string ColumnescriptionDropSqlFormat = "EXEC sp_dropextendedproperty ‘MS_Description‘,‘user‘,dbo,‘table‘,[{0}],‘column‘,‘{1}‘;\r\n";
19 private const string CheckTableExistsSqlFormat = "IF OBJECT_ID(N‘{0}‘,N‘U‘) IS NOT NULL \r\nBEGIN \r\n";
20 private const string EndStr = "END";
21 private const string Tab = " ";
22
23 public bool GenDrop { get; set; }
24 public string Path { get; set; }
25
26 private string GetDescriptionSql(string path)
27 {
28 var sb = new StringBuilder();
29 var fs = File.OpenRead(path);
30 var fileRd = new StreamReader(fs);
31 var str = fileRd.ReadToEnd();
32 var tableMatch = _tableReg.Match(str);
33 if (tableMatch.Length < 2) return string.Empty;
34
35 var tableName = tableMatch.Groups[2].Value;
36 var tableDes = tableMatch.Groups[1].Value;
37 if (string.IsNullOrEmpty(tableName) || string.IsNullOrEmpty(tableDes)) return string.Empty;
38
39 var columnStr = str.Substring(str.IndexOf("(", StringComparison.Ordinal));
40 var matches = _columnsReg.Matches(columnStr);
41
42 sb.AppendFormat(CheckTableExistsSqlFormat, tableName);
43
44 sb.Append(Tab);
45 if (GenDrop)
46 sb.AppendFormat(TableDescriptionDropSqlFormat, tableName);
47 else
48 sb.AppendFormat(TableDescriptionCrateSqlFormat, tableDes, tableName);
49 foreach (Match match in matches)
50 {
51 var columnName = match.Groups[1].Value;
52 var description = match.Groups[2].Value;
53 if (string.IsNullOrEmpty(columnName) || string.IsNullOrEmpty(description))
54 continue;
55 sb.Append(Tab);
56 if (GenDrop)
57 sb.AppendFormat(ColumnescriptionDropSqlFormat, tableName, columnName);
58 else
59 sb.AppendFormat(ColumnDescriptionCrateSqlFormat, description, tableName, columnName);
60 }
61
62 sb.AppendLine(EndStr);
63 return sb.ToString();
64 }
65
66
67 public string GetGenerateSql()
68 {
69 Func<string, List<string>> getFolderSqlNotes = null;
70 getFolderSqlNotes = path =>
71 {
72 var listAll = new List<string>();
73 var files = Directory.GetFiles(path);
74 var dirs = Directory.GetDirectories(path);
75 foreach (string t in dirs)
76 {
77 listAll.AddRange(getFolderSqlNotes(t)); ;
78 }
79 var listStr = files.Where(m => m.EndsWith(".sql")).Select(GetDescriptionSql).ToList();
80 listAll.AddRange(listStr);
81 return listAll;
82 };
83 var list = getFolderSqlNotes(Path);
84 return string.Join("\r\n", list);
85 }
86
87 }
88
89 }

SqlNotesGenerator

CodeSimith模版

  1 <%--
2 Name:
3 Author:
4 Description:
5 --%>
6 <%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="" Inherits="OutputFileCodeTemplate" Debug="False" Description="Template description here." %>
7 <%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context" Optional="True" Description="the table name" %>
8 <%@ Assembly Name="SchemaExplorer" %>
9 <%@ Import Namespace="SchemaExplorer" %>
10 <%@ Assembly Name="CodeSmith.BaseTemplates" %>
11 <%@ Import Namespace="CodeSmith.BaseTemplates" %>
12 <%@ Assembly Name="CodeSmith.CustomProperties" %>
13 <%@ Import Namespace="CodeSmith.CustomProperties" %>
14 //------------------------------------------------------------------------------
15 // <auto-generated>
16 // This code generated by the tool, do not propose to amend
17 // Generation time:<%=DateTime.Now%>
18 // </auto-generated>
19 //------------------------------------------------------------------------------
20 using System;
21 using System.Data;
22 using System.Runtime.Serialization;
23 using XDbFramework;
24 using BPM_M01.DataAccessLayer.Base;
25 using System.Xml.Serialization;
26 using System.Diagnostics;
27 using System.CodeDom.Compiler;
28
29 namespace <%=Namespace%>
30 {
31 [Table(TableName = <%=this.SourceTable.Name%>.Table.Name ,Descripton = "<%=this.SourceTable.Description%>",GenreratePK = <%=GenreratePK.ToString().ToLower()%>)]
32 [GeneratedCodeAttribute("System.Xml", "2.0.50727.4927")]
33 [DebuggerStepThroughAttribute()]
34 public partial class <%=this.SourceTable.Name%> : DtoBase
35 {
36 public static class Table
37 {
38 public const string Name = "<%=this.SourceTable.Name%>";
39 }
40 public static class Columns
41 {
42 <%for(int i=0; i<this.SourceTable.Columns.Count;i++)
43 {
44 string colName=this.SourceTable.Columns[i].Name;%>
45 public const string <%=colName%> = "<%=colName%>";
46 public const string <%=colName%>FullName =Table.Name + "." + "<%=colName%>";
47 <%}%>
48 }
49
50 <%for(int i=0; i<this.SourceTable.Columns.Count;i++)
51 {
52 int namelength=this.SourceTable.Columns[i].Name.Length;
53 string colName=this.SourceTable.Columns[i].Name;
54 if(colName == "ID" || colName == "IDNO") continue;
55 string titleCaseColumName = colName.Substring(0,1).ToUpper() + colName.Substring(1,colName.Length-1);
56 %>
57
58 /// <summary>
59 /// <%=this.SourceTable.Columns[i].Description%>
60 /// </summary>
61 <%if(this.SourceTable.Columns[i].IsPrimaryKeyMember){%>
62 [Column(KeyType = KeyTypeEnum.PrimaryKey,FullName="<%=this.SourceTable.Name%>.<%=this.SourceTable.Columns[i].Name%>", ColumnName="<%=this.SourceTable.Columns[i].Name%>",Index=<%=i%>,Description="<%=this.SourceTable.Columns[i].Description%>")]
63 <%}%>
64 <%else{%>
65 <%if(this.SourceTable.Columns[i].IsForeignKeyMember)%>
66 <%//
67 foreach(TableKeySchema tks in SourceTable.ForeignKeys)
68 {
69 //
70
71 foreach(MemberColumnSchema mcs in tks.ForeignKeyMemberColumns)
72 {
73
74 //
75 if(mcs.Name == SourceTable.Columns[i].Name)
76 {
77 TableSchema ts= tks.PrimaryKeyTable;%>
78 [Column(ColumnName=Columns.<%=colName%>,KeyType = KeyTypeEnum.ForeignKey,FullName=Columns.<%=colName%>FullName,CType=typeof(<%=GetCSharpVariableType(this.SourceTable.Columns[i])%>),ForeignKeyTableName="<%=ts.Name%>",ForeignKeyFiledName="<%=ts.PrimaryKey.MemberColumns[0].Name%>", DbType=<%=GetSqlDBType(this.SourceTable.Columns[i].NativeType)%> Index=<%=i%>,Description="<%=this.SourceTable.Columns[i].Description%>")]
79 <% break;
80 }
81 }
82 }
83 %>
84 <%else{%>
85 [Column(ColumnName=Columns.<%=colName%>,FullName=Columns.<%=colName%>FullName,Index=<%=i%>,CType=typeof(<%=GetCSharpVariableType(this.SourceTable.Columns[i])%>),Description="<%=this.SourceTable.Columns[i].Description%>")]
86 <%}%>
87 <%}%>
88 [DataMember(Order = <%=i%>)]
89 public virtual <%=GetCSharpVariableType(this.SourceTable.Columns[i])%> <%=titleCaseColumName%>{get;set;}
90
91 <%}%>
92 }
93 }
94
95 <script runat="template">
96 // Override the OutputFile property and assign our specific settings to it.
97 [FileDialog(FileDialogType.Save, Title="Select Output File", Filter="C# Files (*.cs)|*.cs", DefaultExtension=".cs")]
98 public override string OutputFile
99 {
100 get {return base.OutputFile;}
101 set {base.OutputFile = value;}
102 }
103 private string _Namespace;
104 public string Namespace
105 {
106 get{return _Namespace;}
107 set{_Namespace = value;}
108 }
109
110 public bool GenreratePK{get;set;}
111 </script>
112 <script runat="template">
113 public string GetSqlDBType(string type)
114 {
115 switch(type)
116 {
117 case "int": return "SqlDbType.Int,";
118 case "bit": return "SqlDbType.Bit,";
119 case "bigint": return "SqlDbType.BigInt,";
120 case "tinyint": return "SqlDbType.TinyInt,";
121 case "nvarchar": return "SqlDbType.NVarChar,";
122 case "date": return "SqlDbType.Date,";
123 case "datetime": return "SqlDbType.DateTime,";
124 case "char": return "SqlDbType.Char,";
125 case "decimal": return "SqlDbType.Decimal,";
126 case "float": return "SqlDbType.Float,";
127 case "image": return "SqlDbType.Image,";
128 case "money": return "SqlDbType.Money,";
129 case "nchar": return "SqlDbType.NChar,";
130 case "ntext": return "SqlDbType.NText,";
131 case "real": return "SqlDbType.Real,";
132 case "smalldatetime": return "SqlDbType.SmallDateTime,";
133 case "smallint": return "SqlDbType.SmallInt,";
134 case "smallmoney": return "SqlDbType.SmallMoney,";
135 case "text": return "SqlDbType.Text,";
136 case "timestamp": return "SqlDbType.Timestamp,";
137 case "udt": return "SqlDbType.Udt,";
138 case "uniqueidentifier": return "SqlDbType.UniqueIdentifier,";
139 case "varbinary": return "SqlDbType.VarBinary,";
140 case "varchar": return "SqlDbType.VarChar,";
141 case "variant": return "SqlDbType.Variant,";
142 case "xml": return "SqlDbType.Xml,";
143 default : return "";
144 }
145
146 }
147 public string GetCSharpVariableType(ColumnSchema column)
148 {
149 switch (column.DataType)
150 {
151 case DbType.AnsiString: return "string";
152 case DbType.AnsiStringFixedLength: return "string";
153 case DbType.Binary: return "byte[]";
154 case DbType.Boolean: return "bool?";
155 case DbType.Byte: return "byte";
156 case DbType.Currency: return "decimal?";
157 case DbType.Date: return "DateTime?";
158 case DbType.DateTime: return "DateTime?";
159 case DbType.Decimal: return "decimal?";
160 case DbType.Double: return "double?";
161 case DbType.Guid: return "Guid";
162 case DbType.Int16: return "short?";
163 case DbType.Int32: return "int?";
164 case DbType.Int64: return "long?";
165 case DbType.Object: return "object";
166 case DbType.SByte: return "sbyte";
167 case DbType.Single: return "float?";
168 case DbType.String: return "string";
169 case DbType.StringFixedLength: return "string";
170 case DbType.Time: return "TimeSpan";
171 case DbType.UInt16: return "ushort?";
172 case DbType.UInt32: return "uint?";
173 case DbType.UInt64: return "ulong?";
174 case DbType.VarNumeric: return "decimal?";
175 default:
176 {
177 return "__UNKNOWN__" + column.NativeType;
178 }
179 }
180 }
181 </script>

代码

下载

GenrerateSqlDescription_8_28.zip

时间: 2024-12-14 01:29:42

小程序大智慧,sqlserver 注释提取工具的相关文章

webstorm开发微信小程序代码提醒(webstorm开发工具)

使用了微信提供的开发工具是真心难用,卡顿厉害.中英文切写注释换相当不爽.还没办法多开窗口,相信大家也遇到过这种现象. 下边我们介绍下webstorm来开发微信小程序的一些配置: 1.首先FileType下Cascading Style Sheet 添加*.wxss 1.png 2.FileType下HTML 添加*.wxml 2.png 3.将其中的wecharCode.jar下载下来,然后在webStorm 的 File -> import settings 中导入即可 3.png 配置已经完

小程序: 微信web开发者工具

1. 下载.安装  微信web开发者工具 - 用于之后的小程序开发     (1) 下载 网址:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html -选择对应的版本(32位.64位) (2) 安装 双击安装包-出现安装向导-点击 下一步-完成安装 (3) 运行"微信web开发者工具"-使用手机微信扫码登录 原文地址:https://www.cnblogs.com/ljr210/p/9928625.html

Java 如何将程序中的注释提取出来生成说明文档

第一种方法: 可以使用JavaDoc工具.它可以从程序源码中将类.方法.成员变量等文档注释抽取出来形成一个与源代码配套的API帮助文档.但是在编写代码时要以一定的规范做注释才可以.通过JavaDoc实现工具就可以同时生成代码的开发文档了.JavaDoc工具位于 C:\Program Files\Java\jdk1.6.0_10\bin 路径下. 其中/**...*/这种注释用于支持JavaDoc工具,还有一些以@开头的标识信息也可以抽取出来,如下图. 这里使用源码中StringBuffer.ja

微信小程序(10)--开发者工具更新以后wxss编译错误

更新最新版微信开发者工具后,出现下面报错: 解决办法: 1.在控制台输入openVendor() ,确定Enter: 2.清除里面的wcc.exe  wcsc.exe : 3.重启开发者工具 原文地址:https://www.cnblogs.com/juewuzhe/p/8227621.html

微信小程序购物商城系统开发系列-工具篇

微信小程序开放公测以来,一夜之间在各种技术社区中就火起来啦.对于它 估计大家都不陌生了,对于它未来的价值就不再赘述,简单一句话:可以把小程序简单理解为一个新的操作系统.新的生态,未来大部分应用场景都将给予微信小程序进行研发.基于对它的敬畏以及便于大家快速上手,特整理微信小程序商城开发系列,未来将持续增加微信小程序技术文章,让大家可全面了解如何快速开发微信小程序商城. 本篇文章主要介绍微信小程序官方提供的开发工具,俗话说:欲工善其身,必先利其器. 小程序开发文档地址https://mp.weixi

HotApp小程序统计,第一个专业的微信第三方小程序统计工具

1.什么是HotApp小程序统计 HotApp小程序统计是第一个微信第三方小程序统计工具,就像做android 和 ios开发的人知道友盟统计一样,小程序也需要有个统计工具. 通过这个工具,可以知道小程序的每日新增,每日启动次数,总用户,每天的活跃用户,很多人可能就会说,微信已经提供了,那还需要这个工具做什么? 因为微信只能看到前一天的新增用户,启动次数等数据,而当日的数据,微信的统计还不能提供. HotApp小程序统计 网址:www.weixin.hotapp.cn 2.HotApp小程序到底

微信公众平台小程序开发教程

? 本文档将带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果.这个小程序的首页将会显示欢迎语以及当前用户的微信头像,点击头像,可以在新开的页面中查看当前小程序的启动日志.下载源码 1. 获取微信小程序的 AppID 如果你是收邀请的开发者,我们会提供一个帐号,利用提供的帐号,登录 https://mp.weixin.qq.com ,就可以在网站的“设置”-“开发者设置”中,查看到微信小程序的 AppID 了,注意不可直接使用服务号或订阅号的 AppID . 如果是游客模式,

微信小程序开发教程

9月21日晚发布的微信公众平台·小程序内侧邀请,微信应用号(小程序,「应用号」的新称呼)终于来了!目前还处于内测阶段,微信只邀请了部分企业参与封测.想必大家都关心应用号的最终形态到底是什么样子? 怎样将一个「服务号」改造成为「小程序」?相信很多技术人员开始关注,会不会取代APP开发,一些职位会不会被取代. 现在带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果.这个小程序的首页将会显示欢迎语以及当前用户的微信头像,点击头像,可以在新开的页面中查看当前小程序的启动日志.下载源码

微信小程序开发简易教程

本文档将带你一步步创建完成一个微信小程序www . qixoo.com,并可以在手机上体验该小程序的实际效果.这个小程序的首页将会显示欢迎语以及当前用户的微信头像,点击头像,可以在新开的页面中查看当前小程序的启动日志.下载源码 1. 获取微信小程序的 AppID 登录 https://mp.weixin.qq.com ,就可以在网站的"设置"-"开发者设置"中,查看到微信小程序的 AppID 了,注意不可直接使用服务号或订阅号的 AppID . 注意:如果要以非管理