Visual Studio下使用Code Snippet

现在项目中事务处理是在DAO中手工控制的,必须首先获得连接,开启事务,成功提交事务,失败回滚事务。典型的代码结构如下:

 

using (var conn = ConnectionManager)
{
	try
	{
		conn.BeginTransaction();	
	
		.... // excute SQL

		conn.Commit();
	}
	catch (Exception e)
	{
		conn.Rollback();
		throw e;
	}
}
 

我对此感到很不舒服,代码中真正有用的只是执行SQL,至于打开连接、处理事务等操作在每个方法中都是一样的,在每个方法中重复这样的代码是典型的bad smell,于是我在BaseDAO中添加了ExecuteInTransaction方法,它接收一个Action委托,Action委托来执行SQL。ExecuteInTransaction实现如下:

 

protected void ExecuteInTransaction(Action dbOp)
{
	using (var conn = ConnectionManager)
	{
		try
		{
			conn.BeginTransaction();

			dbOp.Invoke();

			conn.Commit();
		}
		catch (Exception e)
		{
			conn.Rollback();
			throw e;
		}
	}
}
 

这样封装之后,要执行数据库事务就简单多了,对于最开始的代码现在就可以写成:

 

ExecuteInTransaction( () => {
	... // excute SQL
});
 

我觉得这样改动挺好,也没和技术经理商量,技术经理发现之后,却勒令我改回来。他给我的理由是这样性能太差,为此他专门找了一篇MSDN上的文章(Writing Faster Managed Code: Know What Things Cost )来证明这一点。这是他的惯用手段,每次他说服我改动代码时都会来拿性能来说事。我很不屑于他的这一点,我觉得开发效率和减少BUG才是优先考虑要素,大师Donald E. Knuth早就说过过早优化是万恶之源。但我还是改了,我的理由是“给代码带来了不一致性”,毕竟我没有理由要别人将他们的代码也改成这样。我坦承我一旦觉得原有代码写得不好,就很容易引发“重构”的冲动,但是我又不能改动别人的代码,这样就导致整个项目代码的不一致了。不晓得大家有没有这样的冲动?

 

到目前为止,我似乎说的是无关主题的废话,但别急,我马上就要进入正题了。既然要改代码,复制/粘贴是任何人都会用的方法,但我不想这样做。我改动的地方只有五六处,不多,可能复制/粘贴的速度会更快,但于我的技能却不会有任何提高,我喜欢有技术含量的偷懒。我早知道Visual Studio下有Code Snippet功能,可以自定义代码模板,但从来没有使用过,这次是个好机会。

 

 

第一步是选择模板目录,从菜单选择Tools -> Code Snippets Manager...,或者使用快捷键C+K,C+B。VS(Visual Studio)默认带有My Code Snippets目录,可以将自定义的代码模板放在其下,实际目录是Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets。要添加一个新的模板目录,只需要点击"Add..."按钮,然后选择目录就可以了。我添加了一个叫做VS_CodeSnippet的模板目录。如图:

 

 

 

第二步就是创建代码模板。凡是在模板目录下文件名以.snippet结尾的文件都会认为是代码模板,代码模板是XML格式,需要遵守一定的格式规范。代码模板主要分为三部分,描述信息、变量声明和模板定义。描述信息置于Header部分,最重要的是Shortcut信息,当在VS中输入这个Shortcut,然后再按Tab键,就会用模板的内容来替换Shortcut。我这个模板的Shortcut定义为dao_execute_in_transaction。变量声明置于Snippet的Declarations下,我只定义了一个变量,取名为DBOperation。模板定义置于Snippet的Code下,模板中通过$TempVar$的形式来引用模板变量。以下是我这个模板的完整代码:

 

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
	<CodeSnippet Format="1.0.0">
		<Header>
			<Title>dao_execute_in_transaction</Title>
			<Shortcut>dao_execute_in_transaction</Shortcut>
			<Description>Code snippet for execute sql in transaction</Description>
			<Author>Marlon Yao</Author>
			<SnippetTypes>
				<SnippetType>Expansion</SnippetType>
			</SnippetTypes>
		</Header>
		<Snippet>
			<Declarations>
				<Literal>
					<ID>DBOperation</ID>
					<Default>sql</Default>
					<ToolTip>Transaction Code</ToolTip>
				</Literal>
			</Declarations>
			<Code Language="csharp"><![CDATA[using (var conn = ConnectionManager)
            {
                try
                {
                    conn.BeginTransaction();
                    ExecuteNonQuery($DBOperation$);
                    conn.Commit();
                }
                catch (Exception e)
                {
                    conn.Rollback();
                    throw e;
                }
            }]]>
			</Code>
		</Snippet>
	</CodeSnippet>
</CodeSnippets>

 

我只用很少的功能,写时可以参考VS自带的模板。

 

 

最后就是使用代码模板。使用起来很简单,只需要输入代码模板中定义的Shortcut,对于我这个模板来说就是,dao_execute_in_transaction,输入时VS会自动给予提示(也可以手动键入C+K,C+W来补全)。

 

 

输入dao_execute_in_transaction,然后按Tab键,就会将dao_execute_in_transaction替换成模板内容,并且光标定位在第一个模板变量处。

 

 

如果定义了多个模板变量,按Tab键可以切换到下一个模板变量处,最后按Enter键进入正常编辑模式。

 

定义好代码模板之后,修改起来就简单多了,最重要的是它还可以在以后的编程中用到。我仍旧不喜欢这种代码重复的方式,但这却不是我要并且能关心的事。VS的Code Snippets功能很强大,我只使用很小一部分功能,但也却足以应付大部分情况了,对于它的高级功能等到碰到问题时再去了解。

你可能感兴趣的:(DAO,sql,C++,c,C#)