转自:周公

最近在项目中用到了有关SQL Server管理任务方面的编程实现,有了一些自己的心得体会,想在此跟大家分享一下,在工作中用到了SMO/SQL CLR/SSIS等方面的知识,在国内这方面的文章并不多见,有也是一些零星的应用,特别是SSIS部分国内外的文章大都是讲解如何拖拽控件的,在开发过程中周公除了参阅SQL Server帮助文档、MSDN及StackOverFlow等网站,这些网站基本上都是英文的,为了便于一些英文不好的开发者学习,周公在自己的理解上加以整理成系列,不到之处请大家谅解。
SMO简介
SMO是英文SQL Server Management Objects的缩写,意思是SQL Server管理对象系列,包含了一些列的命名空间(namespace)、动态链接库(dll)和类(class)。这些类偏重于SQL Server的管理,并且在底层是通过SQL Server数据库提供程序(System.Data.SqlClient)下的类来与SQL Server来进行交互的。可以通过编程的方式利用SMO来管理SQL Server7.0以上的版本(SQL Server 7.0/2000/2005/2008),如果低于以上版本的SQL Server则无法利用SMO来管理(除了历史原因遗留的系统,在现在的开发中那些不受支持的SQL Server算是和Windows95一样的古董了)。同时,要使用SMO的话,必须安装SQL Server Native Client,一般情况下当我们安装.Net Framework2.0以上版本或者SQL Server2005以上版本时就会自动安装上了。
在32位系统下如果安装的是SQL Server2005并且没有更改安装路径,则SMO程序集的路径是:C:\Program Files\Microsoft SQL Server\90\SDK\Assemblies,相应的,如果安装的是SQL Server2008,则SMO程序集的路径就是C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies,如果是在64位系统下安装,则根据安装的SQL Server的版本来判断是在Program Files (x86)还是在Program Files下面的对应目录下。
在SMO中有如下命名空间:Microsoft.SqlServer.Management.Common、Microsoft.SqlServer.Management.Nmo、Microsoft.SqlServer.Management.Smo、Microsoft.SqlServer.Management.Smo.Agent、Microsoft.SqlServer.Management.Smo.Broker、Microsoft.SqlServer.Management.Smo.Mail、Microsoft.SqlServer.Management.Smo.RegisteredServers、Microsoft.SqlServer.Management.Smo.Wmi、Microsoft.SqlServer.Management.Trace,关于这些命名空间在哪个dll中以及该命名空间下有哪些类,大家可以查阅SQL Server的帮助文章或者查阅在线MSDN,例如查看命名空间下的类可以浏览:http://msdn.microsoft.com/zh-cn/library/microsoft.sqlserver.management.smo(v=sql.100)
SMO体系架构
我们知道在SQL Server体系中处于顶层是SQL Server实例,每个实例会有多个数据库,每个数据库会有多个表、存储过程、函数、登录账号等,每个表会有列、索引、主键等信息,每个列会有列名、默认值、字段大小等信息,在SMO中有与之相对应的一套类体系结构。 

在DatabaseCollection中每个元素都是一个Database类的实例,分别对应数据实例中的一个数据库;在TableCollection中每个元素都是一个Table的实例,分别对应数据库中的一个表;在ColumnCollection中每个元素都是一个Column类的实例,分别对应表中的每一列,以上这些类都位于Microsoft.SqlServer.Management.Smo命名空间下,在Microsoft.SqlServer.Smo.dll这个dll中。
当然,在Microsoft.SqlServer.Management.Smo命名空间中的类远不止上面提到的这些,上面的表格只是做了一个简单的类比。
SMO用法示例
上面的文章只是做了一个简单的介绍,也许通过上面枯燥的介绍大家没什么印象,下面通过一段简单的代码来简单演示一下用法,首先要添加响应的引用。在VS2008中可以直接通过下面的方式添加引用:

但是在VS2010中就没有这么方便了,它使用了过滤属性(而且还无法禁用掉或者进行设置),使得无法添加这些程序集,如下图:

我看到有人在Stack Overflow提了和我疑惑相同的问题,别人给了一个答案就是在VS2010中安装Muse.VSExtensions来解决,安装地址:http://visualstudiogallery.msdn.microsoft.com/36a6eb45-a7b1-47c3-9e85-09f0aef6e879/,我尝试了一下不是很理想,不过Muse.VSExtensions还提供了其它的功能(比如移除未使用的程序集)还是不错的。
注意在编译下面的代码之前需要添加对microsoft.sqlserver.connectioninfo.dll和microsoft.sqlserver.smo.dll的引用。
代码如下:

  1. using System;
  2. using Microsoft.SqlServer.Management.Common;//需添加microsoft.sqlserver.connectioninfo.dll的引用
  3. using Microsoft.SqlServer.Management.Smo;//需添加microsoft.sqlserver.smo.dll的引用
  4.  
  5. namespace SSISStudy
  6. {
  7. /// <summary>
  8. /// SQL Server编程些列文章(1):SMO介绍的配套代码
  9. /// 作者:周公
  10. /// 创建日期:2012-05-17
  11. /// 博客地址:http://blog.csdn.net/zhoufoxcn http://zhoufoxcn.blog.51cto.com
  12. /// 新浪微博地址:http://weibo.com/zhoufoxcn
  13. /// </summary>
  14. class SMODemo01
  15. {
  16. /// <summary>
  17. /// 显示数据库的概要情况
  18. /// </summary>
  19. public static void ShowServerInfo()
  20. {
  21. //创建ServerConnection的实例
  22. ServerConnection connection = new ServerConnection();
  23. //指定连接字符串
  24. connection.ConnectionString = "Data Source=goodapp;Initial Catalog=master;User ID=sa;Password=root;";
  25. //实例化Server
  26. Server server = new Server(connection);
  27. Console.WriteLine("ActiveDirectory:{0}", server.ActiveDirectory);
  28. Console.WriteLine("InstanceName:{0}",server.InstanceName);
  29.  
  30. //列出当前SQL Server实例中的登录用户
  31. foreach (Login login in server.Logins)
  32. {
  33. Console.WriteLine("Name:{0},CreateDate:{1},DefaultDatabase:{2}", login.Name, login.CreateDate, login.DefaultDatabase);
  34. }
  35. //通过索引方式找到master数据库
  36. Database db = server.Databases["master"];
  37. Console.WriteLine("Database:{0}", db.Name);
  38. Console.WriteLine("CreateDate:{0},Dbo:{1}", db.CreateDate, db.Owner);
  39. Console.WriteLine("DataSpaceUsage:{0},SpaceAvailable:{1}", db.DataSpaceUsage, db.SpaceAvailable);
  40. Console.WriteLine("PrimaryFilePath:{0}", db.PrimaryFilePath);
  41. //列出master数据库下每个表的概要信息
  42. foreach (Table table in db.Tables)
  43. {
  44. Console.WriteLine("\tTable:{0},DataSpaceUsed:{1},CreateDate:{2}", table.Name, table.DataSpaceUsed, table.CreateDate);
  45. //urnCollection.Add(table.Urn);
  46. //列出每个表中每个列的概要信息
  47. foreach (Column column in table.Columns)
  48. {
  49. Console.WriteLine("\t\tColumn:{0},DataType:{1},Nullable:{2}", column.Name, column.DataType, column.Nullable);
  50. }
  51. }
  52. //列出master数据库中的角色信息
  53. foreach(DatabaseRole dbRole in db.Roles)
  54. {
  55. Console.WriteLine("DB Role {0} Created at {1}", dbRole.Name, dbRole.CreateDate);
  56. }
  57.  
  58. Console.ReadLine();
  59. }
  60.  
  61. }
  62. }

程序的执行效果如下:

通过上面的代码可以获取很多有关数据库的信息,而在代码中我们没有写一行SQL语句,而在之前周公曾写过一篇博客《在.NET中根据SQL Server系统表获取数据库管理信息》,在其中为了查找这些信息周公是查了很多资料才知道SQL语句的写法,使用SMO之后连SQL语句都免了,可见利用SMO来管理数据库的方便性。在后续的篇幅中周公将讲述如何利用SMO来获取SQL Server中数据库的创建语句及如何利用SMO来创建Job。

在上一篇周公简单讲述了SMO的一些基本概念,实际上SMO体系结构远不止周公在上一篇中讲述的那么简单,下图是MSDN上给出的一个完整的结构图:

上图是一个完整的涉及到各种关系的结构图。不过它们之间的层次结构关系周公已经在上一篇做了简单概述。
在本篇中周公还是在上一篇的基础上再做稍微深入一点的介绍,在本篇中主要讲述如何获取数据库常见对象信息,并且如何利用SMO来进行一些日常操作:如创建Login,创建数据库、备份数据库和还原数据库。执行上面这些操作的SQL语句也许我们已经写过,下面我们来看看利用SMO来操作的代码将如何写。为了便于理解,在代码中的注释比较详尽,所以本篇中代码之外的讲解就不多了。另外,需要注意的是SMO的dll的版本随着升级变化比较大,这一点不同.NET Framework,没有考虑向下兼容。
代码如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.SqlServer.Management.Smo.RegisteredServers;//在microsoft.sqlserver.smo.dll中
  6. using Microsoft.SqlServer.Management.Smo;//需添加microsoft.sqlserver.smo.dll的引用
  7. using Microsoft.SqlServer.Management.Common;//需添加microsoft.sqlserver.connectioninfo.dll的引用
  8.  
  9. namespace SSISStudy
  10. {
  11. /// <summary>
  12. /// SQL Server编程些列文章(2):SMO常用对象的有关操作
  13. /// 作者:周公
  14. /// 创建日期:2012-05-23
  15. /// 博客地址:http://blog.csdn.net/zhoufoxcn http://zhoufoxcn.blog.51cto.com
  16. /// 新浪微博地址:http://weibo.com/zhoufoxcn
  17. class SMODemo02
  18. {
  19. /// <summary>
  20. /// 显示数据库常见对象信息示例,本方法中的代码只针对9.0版本的SMO dll(SQL2005附带程序集)
  21. /// </summary>
  22. public static void ShowSMOObjects()
  23. {
  24. Console.WriteLine("Server Group Information");
  25. foreach (ServerGroup serverGroup in SmoApplication.SqlServerRegistrations.ServerGroups)
  26. {
  27. Console.WriteLine("Group Name:{0},Path:{1},ServerType:{2},State:{3},Urn:{4}", serverGroup.Name, serverGroup.Path, serverGroup.ServerType, serverGroup.State, serverGroup.Urn);
  28. }
  29.  
  30. Console.WriteLine("Registered Server Information");
  31. foreach (RegisteredServer regServer in SmoApplication.SqlServerRegistrations.RegisteredServers)
  32. {
  33. Console.WriteLine("Server Name:{0},Login:{1},State:{2},Urn:{3}", regServer.Name, regServer.Login, regServer.State, regServer.Urn);
  34. }
  35.  
  36. //创建ServerConnection的实例
  37. ServerConnection connection = new ServerConnection();
  38. //指定连接字符串
  39. connection.ConnectionString = "Data Source=goodapp;Initial Catalog=master;User ID=sa;Password=root;";
  40. //实例化Server
  41. Server server = new Server(connection);
  42. Console.WriteLine("ActiveDirectory:{0},InstanceName:{1}", server.ActiveDirectory, server.InstanceName);
  43. //下面列出每个数据库的具体信息
  44. foreach (Database db in server.Databases)
  45. {
  46. Console.WriteLine("Database Name:{0},ActiveDirectory:{1},ActiveConnections:{2},DataSpaceUsage:{3},PrimaryFilePath:{4}", db.Name, db.ActiveDirectory, db.ActiveConnections, db.DataSpaceUsage, db.PrimaryFilePath);
  47. //列出数据库的数据文件文件组信息
  48. foreach (FileGroup fileGroup in db.FileGroups)
  49. {
  50. Console.WriteLine("\tFileGroup Name:{0},Size:{1},State:{2},Urn:{3}", fileGroup.Name, fileGroup.Size, fileGroup.State, fileGroup.Urn);
  51. //列出每个文件组中的数据文件信息
  52. foreach (DataFile dataFile in fileGroup.Files)
  53. {
  54. Console.WriteLine("\t\tDataFile Name:{0},Size:{1},State:{2},Urn:{3},FileName:{4}", dataFile.Name, dataFile.Size, dataFile.State, dataFile.Urn, dataFile.FileName);
  55. }
  56. }
  57. //列出数据库日志文件信息
  58. foreach (LogFile logFile in db.LogFiles)
  59. {
  60. Console.WriteLine("\tLogFile Name:{0},Size:{1},State:{2},Urn:{3},FileName:{4}", logFile.Name, logFile.Size, logFile.State,logFile.Urn,logFile.FileName);
  61. }
  62. }
  63. }
  64. /// <summary>
  65. /// 利用SMO创建SQL登录
  66. /// </summary>
  67. public static void CreateLogin()
  68. {
  69. string loginName = "zhoufoxcn";//要创建的数据库登录名
  70. string loginPassword = "C#.NET";//登录密码
  71.  
  72. //创建ServerConnection的实例
  73. ServerConnection connection = new ServerConnection();
  74. //指定连接字符串
  75. connection.ConnectionString = "Data Source=goodapp;Initial Catalog=master;User ID=sa;Password=root;";
  76. //实例化Server
  77. Server server = new Server(connection);
  78.  
  79. #region [创建数据库登录对象]
  80. //检查在数据库是否已经存在该登录名
  81. var queryLogin = from Login temp in server.Logins
  82. where string.Equals(temp.Name, loginName, StringComparison.CurrentCultureIgnoreCase)
  83. select temp;
  84. Login login = queryLogin.FirstOrDefault<Login>();
  85. //如果存在就删除
  86. if (login != null)
  87. {
  88. login.Drop();
  89. }
  90. login = new Login(server, loginName);
  91. login.LoginType = LoginType.SqlLogin;//指定登录方式为SQL认证
  92. login.PasswordPolicyEnforced = true;
  93. login.DefaultDatabase = "master";//默认数据库
  94. login.Create(loginPassword);
  95. #endregion
  96. }
  97. /// <summary>
  98. /// 利用SMO创建数据库
  99. /// </summary>
  100. public static void CreateDatabase()
  101. {
  102. string databaseName = "SMODemo";
  103. //创建ServerConnection的实例
  104. ServerConnection connection = new ServerConnection();
  105. //指定连接字符串
  106. connection.ConnectionString = "Data Source=goodapp;Initial Catalog=master;User ID=sa;Password=root;";
  107. //实例化Server
  108. Server server = new Server(connection);
  109.  
  110. #region [创建数据库对象]
  111. //检查在数据库是否已经存在该数据库
  112. var queryDatabase = from Database temp in server.Databases
  113. where string.Equals(temp.Name, databaseName, StringComparison.CurrentCultureIgnoreCase)
  114. select temp;
  115. Database database = queryDatabase.FirstOrDefault<Database>();
  116. //如果存在就删除
  117. if (database != null)
  118. {
  119. database.Drop();
  120. }
  121.  
  122. database = new Database(server, databaseName);
  123. //指定数据库数据文件细节
  124. FileGroup fileGroup = new FileGroup { Name = "PRIMARY", Parent = database, IsDefault = true };
  125. DataFile dataFile = new DataFile
  126. {
  127. Name = databaseName + "_data",
  128. Parent = fileGroup,
  129. FileName = @"F:\SQLData2005\" + databaseName + ".mdf"
  130. };
  131. fileGroup.Files.Add(dataFile);
  132. //指定数据库日志文件细节
  133. LogFile logFile = new LogFile
  134. {
  135. Name = databaseName + "_log",
  136. Parent = database,
  137. FileName = @"F:\SQLData2005\" + databaseName + ".ldf"
  138. };
  139.  
  140. database.FileGroups.Add(fileGroup);
  141. database.LogFiles.Add(logFile);
  142.  
  143. database.Create();
  144. #endregion
  145. }
  146. /// <summary>
  147. /// 利用SMO备份数据库
  148. /// </summary>
  149. public static void BackupDatabase()
  150. {
  151. string databaseName = "msdb";//备份的数据库名
  152. string bkPath = @"C:\";//存放备份后的数据的文件夹
  153. //创建ServerConnection的实例
  154. ServerConnection connection = new ServerConnection();
  155. //指定连接字符串
  156. connection.ConnectionString = "Data Source=goodapp;Initial Catalog=master;User ID=sa;Password=root;";
  157. //实例化Server
  158. Server server = new Server(connection);
  159.  
  160. #region [创建数据库备份对象]
  161. Backup backup = new Backup();
  162. backup.Action = BackupActionType.Database;//完全备份
  163. backup.Database = databaseName;
  164. backup.BackupSetDescription = "Full backup of master";
  165. backup.BackupSetName = "master Backup";
  166. //创建备份设备
  167. BackupDeviceItem bkDeviceItem = new BackupDeviceItem();
  168. bkDeviceItem.DeviceType = DeviceType.File;
  169. bkDeviceItem.Name = bkPath+databaseName+".bak";
  170.  
  171. backup.Devices.Add(bkDeviceItem);
  172. backup.Incremental = false;
  173. backup.LogTruncation = BackupTruncateLogType.Truncate;
  174. backup.SqlBackup(server);
  175. #endregion
  176. }
  177.  
  178. /// <summary>
  179. /// 备份数据库
  180. /// </summary>
  181. public static void RestoreDatabase()
  182. {
  183. string databaseName = "SMODemo";//备份的数据库名
  184. string bkPath = @"C:\";//存放备份后的数据的文件夹
  185. //创建ServerConnection的实例
  186. ServerConnection connection = new ServerConnection();
  187. //指定连接字符串
  188. connection.ConnectionString = "Data Source=goodapp;Initial Catalog=master;User ID=sa;Password=root;";
  189. //实例化Server
  190. Server server = new Server(connection);
  191.  
  192. Restore restore = new Restore();
  193. restore.NoRecovery = false;
  194. restore.NoRewind = false;
  195. restore.Action = RestoreActionType.Database;
  196. restore.Database = databaseName;
  197.  
  198. //创建备份设备
  199. BackupDeviceItem bkDeviceItem = new BackupDeviceItem();
  200. bkDeviceItem.DeviceType = DeviceType.File;
  201. bkDeviceItem.Name = bkPath + databaseName + ".bak";
  202.  
  203. //如果需要重新制定Restore后的数据库的物理文件位置,需要知道数据库文件的逻辑文件名
  204. //可以RESTORE FILELISTONLY 来列出逻辑文件名,如果覆盖已有数据库可以通过SMO来获取
  205. //因本处使用的是刚刚备份的msdb数据库来Restore,所以其分别为"MSDBData"和"MSDBLog"
  206. //如果不指定Restore路径则默认恢复到数据库服务器存放数据的文件夹下
  207. RelocateFile relocateDataFile = new RelocateFile { LogicalFileName = "MSDBData", PhysicalFileName = bkPath + databaseName + ".mdf" };//(databaseName + "_data", bkPath + databaseName + ".mdf");
  208. RelocateFile relocateLogFile = new RelocateFile { LogicalFileName = "MSDBLog", PhysicalFileName = bkPath + databaseName + ".ldf" };//(databaseName + "_log", bkPath + databaseName + ".ldf");
  209.  
  210. restore.Devices.Add(bkDeviceItem);
  211. restore.RelocateFiles.Add(relocateDataFile);
  212. restore.RelocateFiles.Add(relocateLogFile);
  213. restore.SqlRestore(server);
  214. }
  215. }
  216. }

执行结果在这里就不贴图了,反正是是在周公家里的中文环境和办公室英文环境中测试通过。预先透漏一下,下一篇将讲述如何获取SQL Server的对象的创建SQL语句,比如表、存储过程、函数等。

[转]SQL Server编程:SMO介绍的更多相关文章

  1. SQL Server编程系列(1):SMO介绍

    原文:SQL Server编程系列(1):SMO介绍 续篇:SQL Server编程系列(2):SMO常用对象的有关操作 最近在项目中用到了有关SQL Server管理任务方面的编程实现,有了一些自己 ...

  2. (转) SQL Server编程系列(1):SMO介绍

    最近在项目中用到了有关SQL Server管理任务方面的编程实现,有了一些自己的心得体会,想在此跟大家分享一下,在工作中用到了SMO/SQL CLR/SSIS等方面的知识,在国内这方面的文章并不多见, ...

  3. SQL Server编程系列(2):SMO常用对象的有关操作

    原文:SQL Server编程系列(2):SMO常用对象的有关操作 在上一篇周公简单讲述了SMO的一些基本概念,实际上SMO体系结构远不止周公在上一篇中讲述的那么简单,下图是MSDN上给出的一个完整的 ...

  4. Oracle与SQL SERVER编程差异分析(入门)

    网上有关Oracle与SQL SERVER性能差异的文章很多,结论往往是让你根据数据量与预算来选择数据库.但实际项目中,特别是使用 .Net 开发的系统,支持以上两种数据库或者更多已经成为Boss的普 ...

  5. SQL Server群集知识介绍

    集群CLUSTER种类介绍 基于iSCSI的SQL Server 2012群集测试(一)--SQL群集安装 SQL Server群集如何在线检测 群集中的MS DTC分布式事务协调器 一.SQL Se ...

  6. SQL Server编程入门

    SQL编程要比Java编程.C#编程简单许多,下面我们直接讲干货21:04:31 使用变量 局部变量 在T-SQL中,局部变量的名称必须以标记@作为前缀.T-SQL的局部变量其实和Java中的局部变量 ...

  7. SQL Server存储过程多角度介绍

    什么是存储过程: 存储过程(Procedure)类似于C#语言中的方法,它是SQL语句和控制流语句的预编译集合.存储过程存储在数据库内,可由应用程序通过一个调用执行,而且允许用户声明变量.逻辑控制语句 ...

  8. SQL Server编程(02)自定义函数

    在编程过程中,我们通常把特定的功能语句块封装称函数,方便代码的重用.我们可以在SQL Server中自定义函数,根据函数返回值的区别,我们自定义的函数分两种:标量值函数和表值函数. 自定义函数的优点: ...

  9. SQL Server 编程入门经典(3)之T-SQL基本语句

    本章内容简介: 如何从数据库检索数据(SELECT) 如何向表中插入数据(INSERT) 如何适当更新数据(UPDATE) 如何删除表中数据(DELETE) 3.1 基本SELECT语句  如果你在此 ...

随机推荐

  1. mongodb的安装以及客户端

    mongodb是一种非关系型的数据库,与传统的sql有很大的不同,但都是用于数据管理的,本人也是初学,很多地方都是模仿,在这里只是记录本人初次安装mongodb和客户端,记录一下安装的步骤,以便以后用 ...

  2. LN : leetcode 231 Power of Two

    lc 231 Power of Two 231 Power of Two Given an integer, write a function to determine if it is a powe ...

  3. ubuntu下编译VLC源码

    http://blog.csdn.net/beitiandijun/article/details/9225591ubuntu下编译VLC源码 分类: 视频处理 2013-07-02 17:33 57 ...

  4. 使用QTP录制自带Flight小实例

    1.双击打开QTP10.0,启动过程中测试类型选择“WEB”. 2.进入主界面,New——Test,新建一个测试用例. 3.点击Record按钮,Record and settings对话框中,可以选 ...

  5. 在Redux中使用插件createAction之后

    我们知道在React的Redux的中的action在项目开发过程中,一般时使用createAction来生成 举个栗子,小李子: const createTodo=createACtion('CREA ...

  6. jq封装插件

    $.extend()拓展方法: $(function(){ $.extend({ money:function(){ alert("我要努力赚钱") }, money:functi ...

  7. JMeter在linux上分布式压测遇到的坑(三)

    master和slave机要在同一网段内,才能做分布式(Jmeter要配环境变量,这样不用手动起server) 分布式不成功,解决方案: 1.master端和slave端要ping通 2.ping通后 ...

  8. 对vuex的一点理解

    vuex是vue.js的一个状态管理工具,它适用于解决平行组件之间的数据共享问题.一般情况下,我们更多的是父子组件之间通过props或$emit来实现传值,如何不满足以上情况那只有使用vuex进行解决 ...

  9. 数列分块入门1-9 By hzwer

    声明 持续更新,因为博主也是正在学习分块的知识,我很菜的,菜的抠$jio$ 写在前面 分块是个很暴力的算法,但却比暴力优秀的多,分块算法的时间复杂度一般是根号的,他的主要思想是将一个长度是$n$的数列 ...

  10. C++ volatile关键字(转)

    文章来源: http://hedengcheng.com/?p=725 https://www.cnblogs.com/god-of-death/p/7852394.html 1.基本概念 volat ...