前言:
这个文章只要是记录一下,这个工具的诞生过程、作用、其中的技术实在是太简单可以说没有什么技术~主要是锻炼一下写文章的能力!
正文:
在开发项目的时,常常会要维护或变更一些老项目,涉及到简单的几张表的操作,大部分都是ADO操作数据库的代码!写写改改、添加、删除什么的。用那些代码生成器什么的,都需要配置不少东西,况且我真正要生成的只要一小段代码,自食其力,就自己弄一个这样的工具来帮助自己吧。
既然是对SqlServer进行操作的工具,肯定第一步要实现对SqlServer的链接了也就是登陆SqlServer。
登陆功能:
1,使用SqlServer账号密码进行登陆,链接上数据库
2,登陆成功后可以记录下本次登陆的记录以便下次可以快速使用登陆记录进行登陆
界面实现:
如果IP是第一次登陆,登陆的时候我将登陆数据存储到了xml文件里,再次登陆的时候会将所有以存储的记录罗列出来供用户选择。
这里涉及的就是一些XML的读取和写入,贴一下我写的XML操作方法。
/// <summary>
/// 集合写出Xml
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="ls"></param>
public static void DataToXml<T>(List<T> ls,string path)
{
XmlDocument xmldoc = new XmlDocument();
//加入XML的声明段落,<?xml version="1.0" encoding="gb2312"?>
XmlDeclaration xmldecl;
xmldecl = xmldoc.CreateXmlDeclaration("1.0", "gb2312", null);
xmldoc.AppendChild(xmldecl);
//加入一个根元素
var xmlelem = xmldoc.CreateElement("", "Nodes", "");
xmldoc.AppendChild(xmlelem);
//加入另外一个元素
foreach (T s in ls)
{
XmlNode root = xmldoc.SelectSingleNode("Nodes");
XmlElement xe1 = xmldoc.CreateElement("Node");
foreach (PropertyInfo pi in typeof(T).GetProperties())
{
object value = null;
if (s != null)
{
value = pi.GetValue(s, null);
XmlElement xesub1 = xmldoc.CreateElement(pi.Name);
xesub1.InnerText = value == null ? "" : value.ToString();
xe1.AppendChild(xesub1);
root.AppendChild(xe1);
}
}
}
//保存创建好的XML文档 xmldoc.Save(path);
}
/// <summary>
/// Xml生成实体集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xmlpath"></param>
/// <returns></returns>
public static List<T> getxmltomodel<T>(string xmlpath)
{
try
{
#region 遍历xml
XmlDocument _xm = new XmlDocument();
_xm.Load(xmlpath); XmlNodeList xmList = _xm.SelectNodes("/pma_xml_export/database/table");
List<T> _ls = new List<T>();
foreach (XmlNode pageNode in xmList)
{ T _m = Activator.CreateInstance<T>();
foreach (PropertyInfo pi in typeof(T).GetProperties())
{ foreach (XmlNode nd in pageNode.ChildNodes)
{
XmlElement element = (XmlElement)nd;
if (element.GetAttribute("name") == pi.Name)
{
object value = null;
value = element.InnerText;
Type type = pi.GetType();
pi.SetValue(_m, Convert.ChangeType(value, pi.PropertyType), null);
}
} }
_ls.Add((T)_m); }
#endregion return _ls;
}
catch
{
return null;
} }
既然登陆成功了,我们就可以将数据库下的所有库和表查询出来并展示给我们进行选择了。
数据库/表的查询展示:
查询所有数据库方法:
select * from [sysdatabases] order by [name]
查询所有表方法:
select [id], [name] from [sysobjects] where [type] = 'u' order by [name]
得到数据库的数据后就可以绑定到Tree上了,并绑定点击事件,当点击的时候再展示该库下所有的表,这样就可以选择要操作的表了。
表属性查询方法:
/// <summary>
/// 获取表信息
/// </summary>
/// <param name="tablename"></param>
/// <returns></returns>
public DataTable GetTableInfo(string tablename)
{ try
{
string sql = string.Format(@"
SELECT
表名 = d.name,--case when a.colorder=1 then d.name else '' end,
表说明 = case when a.colorder=1 then isnull(f.value,'') else '' end,
字段序号 = a.colorder,
fieldname = a.name,
标识 = case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '√'else '' end,
主键 = 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 '√' else '' end,
sqltype = b.name,
占用字节数 = a.length,
长度 = COLUMNPROPERTY(a.id,a.name,'PRECISION'),
小数位数 = isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),
允许空 = case when a.isnullable=1 then '√'else '' end,
默认值 = isnull(e.text,''),
fieldexplain = isnull(g.[value],'')
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
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
d.name='{0}' --如果只查询指定表,加上此条件
order by
a.id,a.colorder", tablename);
return Service.Data.SqlHelper.DataTable(sql);
}
catch (Exception ex)
{
throw (ex);
}
}
}
代码模板:
模板也是存储在了XML文件里,可以配置多个模板。
生成代码:
这里用的方法很基本了,简单的循环所有字段信息根据模板预留的占位符进行替换生成,与一些常用的代码生成器的做没法比了,不过本着方便自己的想法,这样的工具还是挺好用的,有空大家也可以学习学习他们的做法也是对自己的知识积累。
//我在替换中使用的一些占位符 [tablename] 可替换表的名称
/**************************/
[list][list]为多字段循环列表
[list=][/list]多字段循环列表,会自动去掉最后元素的最后一个符号。
/**************************/
循环体内容中可替换内容有:
[fieldname] 字段名称
[sqltype] 字段类型
[fieldexplain] 字段说明 /**************************/
[replace=xxx][/replace]筛选替换循环体内的变量。
xxx可填:sqltype、fieldname、fieldexplain
文档生成:
后来因为要常看一些表的结构和梳理数据文档所以就弄了一个富文本编辑插件,可以把表的属性生成一个table表格,方便查看,也可以复制到word里面。
知识点:
1,窗体之间如何互相触发事件刷新数据
这个工具就两个界面,当主界面main加载的时候会判断是否已登陆了,如果没有登陆就会加载登陆窗体login。在login中登陆成功后会刷新main中的tree。
实现代码:
在login中定义事件并在登陆成功后触发事件。
/// <summary>
/// 定义登陆成供事件委托
/// </summary>
public delegate void LoginSuccess();
/// <summary>
/// 定义登陆成功事件
/// </summary>
public event LoginSuccess LoginSuccessEvent; /// <summary>
/// 触发登陆成功事件
/// </summary>
protected virtual void OnLoginSuccessEvent()
{
var handler = LoginSuccessEvent;
if (handler != null) handler();
} private void button1_Click(object sender, EventArgs e)
{
this.OnLoginSuccessEvent();
}
main在调用login时,绑定事件回调函数。
private void main_Load(object sender, EventArgs e)
{
login lg=new login();
lg.LoginSuccessEvent += LoginSuccess;
lg.Show();
} void LoginSuccess()
{
textBox1.Text = DateTime.Now.ToString("u");
}
纯属初期学习项目,没什么技术。
如果做的更好点可以用T4之类的模板技术。