![]() |
|
|
|
By: Arshad Ali | Read Comments (8) | Related Tips: More > SQL Server Management Objects SMO |
Solution
Although SQL Server Management Studio (SSMS) is a great tool to manage a SQL Server instance there might be a need to manage your SQL Server instance programmatically.
For example, consider you are developing a build deployment tool, this tool will deploy the build but before that it needs to make sure that the SQL Server and SQL Server Agent services are running, a database is available and online. For this kind of work, you can use SMO, a SQL Server API object model.
The SMO object model represents SQL Server as a hierarchy of objects. On top of this hierarchy is the Server object, beneath it resides all the instance classes.
SMO classes can be categorized into two categories:
How SMO is different from SQL-DMO
SMO object model is based on managed code and implemented as .NET Framework assemblies. It provides several benefits over traditional SQL-DMO along with support for new features introduced with SQL Server 2005 and SQL Server 2008.
For example
An exhaustive list of the comparisons between SQL-DMO and SMO can be found here.
Example
Before you start writing your code using SMO, you need to take reference of several assemblies which contain different namespaces to work with SMO. To add a reference of these assemblies, go to Solution Browser - > References -> Add Reference.Add these commonly used assemblies.

There are a couple of other assemblies which contain namespaces for certain tasks, but few of them are essential to work with SMO. Some of the frequently used namespaces and their purposes are summarized in the below table, other namespaces are used for specific tasks like working with SQL Server Agent where you would reference Microsoft.SqlServer.Management.Smo.Agent etc.
| Namespaces | Purpose |
| Microsoft.SqlServer.Management.Common | It contains the classes which you will require to make a connection to a SQL Server instance and execute Transact-SQL statements directly. |
| Microsoft.SqlServer.Management.Smo | This is the basic namespace which you will need in all SMO applications, it provides classes for core SMO functionalities. It contains utility classes, instance classes, enumerations, event-handler types, and different exception types. |
| Microsoft.SqlServer.Management.Smo.Agent | It provides the classes to manage the SQL Server Agent, for example to manage Job, Alerts etc. |
| Microsoft.SqlServer.Management.Smo.Broker | It provides classes to manage Service Broker components using SMO. |
| Microsoft.SqlServer.Management.Smo.Wmi | It provides classes that represent the SQL Server Windows Management Instrumentation (WMI). With these classes you can start, stop and pause the services of SQL Server, change the protocols and network libraries etc. |
C# Code Block 1
Here I am using the Server instance object to connect to a SQL Server. You can specify authentication mode by setting the LoginSecure property. If you set it to "true", windows authentication will be used or if you set it to "false" SQL Server authentication will be used.
With Login and Password properties you can specify the SQL Server login name and password to be used when connecting to a SQL Server instance when using SQL Server authentication.
|
C# Code Block 1 - Connecting to server |
Server myServer = new Server(@"ARSHADALI\SQL2008"); //Using windows authentication myServer.ConnectionContext.LoginSecure = true; myServer.ConnectionContext.Connect(); //// //Do your work //// if (myServer.ConnectionContext.IsOpen) myServer.ConnectionContext.Disconnect(); //Using SQL Server authentication myServer.ConnectionContext.LoginSecure = false; myServer.ConnectionContext.Login = "SQLLogin"; myServer.ConnectionContext.Password = "entry@2008"; |
C# Code Block 2
Once a connection has been established to the server, I am enumerating through the database collection to list all the database on the connected server. Then I am using another instance class Database which represents the AdventureWorks database. Next I am enumerating through the table, stored procedure and user-defined function collections of this database instance to list all these objects. Finally I am using the Table instance class which represents the Employee table in the AdventureWorks database to enumerate and list all properties and corresponding values.
|
C# Code Block 2 - retrieving databases, tables, SPs, UDFs and Properties |
//List down all the databases on the server
foreach (Database myDatabase in myServer.Databases)
{
Console.WriteLine(myDatabase.Name);
}
Database myAdventureWorks = myServer.Databases["AdventureWorks"];
//List down all the tables of AdventureWorks
foreach (Table myTable in myAdventureWorks.Tables)
{
Console.WriteLine(myTable.Name);
}
//List down all the stored procedures of AdventureWorks
foreach (StoredProcedure myStoredProcedure in myAdventureWorks.StoredProcedures)
{
Console.WriteLine(myStoredProcedure.Name);
}
//List down all the user-defined function of AdventureWorks
foreach (UserDefinedFunction myUserDefinedFunction in myAdventureWorks.UserDefinedFunctions)
{
Console.WriteLine(myUserDefinedFunction.Name);
}
//List down all the properties and its values of [HumanResources].[Employee] table
foreach (Property myTableProperty in myServer.Databases["AdventureWorks"].Tables["Employee",
"HumanResources"].Properties)
{
Console.WriteLine(myTableProperty.Name + " : " + myTableProperty.Value);
} |
C# Code Block 3
This demonstrates the usage of SMO to perform DDL operations.
First I am checking the existence of a database, if it exists dropping it and then creating it.
Next I am creating a Table instance object, then creating Column instance objects and adding it to the created Table object. With each Column object I am setting some property values.
Finally I am creating an Index instance object to create a primary key on the table and at the end I am calling the create method on the Table object to create the table.
|
C# Code Block 3 - Creating a database and table |
//Drop the database if it exists if(myServer.Databases["MyNewDatabase"] != null) myServer.Databases["MyNewDatabase"].Drop(); //Create database called, "MyNewDatabase" Database myDatabase = new Database(myServer, "MyNewDatabase"); myDatabase.Create(); //Create a table instance Table myEmpTable = new Table(myDatabase, "MyEmpTable"); //Add [EmpID] column to created table instance Column empID = new Column(myEmpTable, "EmpID", DataType.Int); empID.Identity = true; myEmpTable.Columns.Add(empID); //Add another column [EmpName] to created table instance Column empName = new Column(myEmpTable, "EmpName", DataType.VarChar(200)); empName.Nullable = true; myEmpTable.Columns.Add(empName); //Add third column [DOJ] to created table instance with default constraint Column DOJ = new Column(myEmpTable, "DOJ", DataType.DateTime); DOJ.AddDefaultConstraint(); // you can specify constraint name here as well DOJ.DefaultConstraint.Text = "GETDATE()"; myEmpTable.Columns.Add(DOJ); // Add primary key index to the table Index primaryKeyIndex = new Index(myEmpTable, "PK_MyEmpTable"); primaryKeyIndex.IndexKeyType = IndexKeyType.DriPrimaryKey; primaryKeyIndex.IndexedColumns.Add(new IndexedColumn(primaryKeyIndex, "EmpID")); myEmpTable.Indexes.Add(primaryKeyIndex); //Unless you call create method, table will not created on the server myEmpTable.Create(); Result:
|
The complete code listing (created using SQL Server 2008 and Visual Studio 2008, although there is not much difference if you are using SQL Server 2005 and Visual Studio 2005) can be found in the below text box.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SqlServer.Management.Smo;
namespace LearnSMO2008
{
class Program
{
static void Main(string[] args)
{
Server myServer = new Server(@"ARSHADALI\SQL2008");
try
{
//Using windows authentication
myServer.ConnectionContext.LoginSecure = true;
//Using SQL Server authentication
//myServer.ConnectionContext.LoginSecure = false;
//myServer.ConnectionContext.Login = "SQLLogin";
//myServer.ConnectionContext.Password = "entry@2008";
myServer.ConnectionContext.Connect();
//AccessingSQLServer(myServer);
DatabaseObjectCreation(myServer);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (myServer.ConnectionContext.IsOpen)
myServer.ConnectionContext.Disconnect();
Console.ReadKey();
}
}
private static void AccessingSQLServer(Server myServer)
{
//List down all the databases on the server
foreach (Database myDatabase in myServer.Databases)
{
Console.WriteLine(myDatabase.Name);
}
Database myAdventureWorks = myServer.Databases["AdventureWorks"];
//List down all the tables of AdventureWorks
foreach (Table myTable in myAdventureWorks.Tables)
{
Console.WriteLine(myTable.Name);
}
//List down all the stored procedures of AdventureWorks
foreach (StoredProcedure myStoredProcedure in myAdventureWorks.StoredProcedures)
{
Console.WriteLine(myStoredProcedure.Name);
}
//List down all the user-defined function of AdventureWorks
foreach (UserDefinedFunction myUserDefinedFunction in myAdventureWorks.UserDefinedFunctions)
{
Console.WriteLine(myUserDefinedFunction.Name);
}
//List down all the properties and its values of [HumanResources].[Employee] table
foreach (Property myTableProperty in myServer.Databases["AdventureWorks"].Tables["Employee",
"HumanResources"].Properties)
{
Console.WriteLine(myTableProperty.Name + " : " + myTableProperty.Value);
}
}
private static void DatabaseObjectCreation(Server myServer)
{
//Drop the database if it exists
if(myServer.Databases["MyNewDatabase"] != null)
myServer.Databases["MyNewDatabase"].Drop();
//Create database called, "MyNewDatabase"
Database myDatabase = new Database(myServer, "MyNewDatabase");
myDatabase.Create();
//Create a table instance
Table myEmpTable = new Table(myDatabase, "MyEmpTable");
//Add [EmpID] column to created table instance
Column empID = new Column(myEmpTable, "EmpID", DataType.Int);
empID.Identity = true;
myEmpTable.Columns.Add(empID);
//Add another column [EmpName] to created table instance
Column empName = new Column(myEmpTable, "EmpName", DataType.VarChar(200));
empName.Nullable = true;
myEmpTable.Columns.Add(empName);
//Add third column [DOJ] to created table instance with default constraint
Column DOJ = new Column(myEmpTable, "DOJ", DataType.DateTime);
DOJ.AddDefaultConstraint(); // you can specify constraint name here as well
DOJ.DefaultConstraint.Text = "GETDATE()";
myEmpTable.Columns.Add(DOJ);
// Add primary key index to the table
Index primaryKeyIndex = new Index(myEmpTable, "PK_MyEmpTable");
primaryKeyIndex.IndexKeyType = IndexKeyType.DriPrimaryKey;
primaryKeyIndex.IndexedColumns.Add(new IndexedColumn(primaryKeyIndex, "EmpID"));
myEmpTable.Indexes.Add(primaryKeyIndex);
//Unless you call create method, table will not created on the server
myEmpTable.Create();
}
}
}
Notes:
Next Steps
For more information review Overview (SMO) on msdn.
| Monday, March 22, 2010 - 10:56:52 AM - phillips_jim | Read The Tip |
|
Would like to seen some examples using PowerShell instead of C#. As a DBA I would be more likely to use PowerShell than C# when using SMO. Can you present a followup tip showing some PowerShell examples? |
|
| Tuesday, April 05, 2011 - 11:44:56 AM - Bill | Read The Tip |
|
Thanks! That helped alot. I made use of the drop and create index scripts :] - it worked great. |
|
| Tuesday, August 14, 2012 - 7:17:28 AM - Jeff Moden | Read The Tip |
|
This is a good post with some nice, simple examples to do things. However, being more of a data troll rather than I front end guy, I'm still confused why folks would spend so much time writing code to do what SQL Server can easily generate scripts for. I also realize that these are simple examples but I'm concerned about code examples like the following...
If a 3rd party application were to drop one of my databases because I just happened to use the same name for the database, I'd be livid even though I could easily restore it. The code really should have a check to STOP running if the database already exists or at least ask the question if it should be dropped. The other thing that I'm concerned with is that the default "growth" settings on most SQL Servers cause huge amounts of both database and operating system fragmentation of databases. It would be nice if you would modify that snippet of code to include such settings and possibly a comment of "See your DBA for what the correct settings should be". The reason for so much concern is that you are a well known and trusted individual with many excellent tips and I'm concerned that front end developers will take your code exactly as it's written and disaster could ensue. As a side bar and as you pointed out, lot's of people spent a lot of time writing SQL DMO and it all had to be rewritten to use SQL SMO. With that thought in mind, I wonder what the future of SQL SMO holds for us. Will it, too, become hopelessly obsolete? It's not a question that I need to have answered. It's a rhetorical question to raise awareness.
|
|
| Wednesday, August 22, 2012 - 7:40:19 AM - Jamil Akbar | Read The Tip |
|
Great post. I am using SQL Server & DMO since a long time. I am using SQL SMO first time to create a routine for database restore but whenever i create object like Dim sqlRestore as New Restore word restore become underlined & shows an error saying that restore is not defined. I have added all references to the project as below Microsoft.SqlServer.ConnectionInfo Microsoft.SqlServer.Smo Microsoft.SqlServer.SqlEnum
also used
Imports Microsoft.SqlServer.Management.Smo Imports Microsoft.SqlServer.Management.Common
Important point: when i declare Server object it again shows error and says "Reference Required to assembly 'Microsoft.SqlServer.Management.sdk.sfc'" after adding that reference server object works well another point i have noted that all refernces that i have added were found in C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies but i didn't found SqlEnum there Please help me to fix this problem. am i missing some step or should i download some additional stuff. I am using VS2010, SQLExpress 2008 and SQL Server Management Studio 2008, SQL Server 2008 also installed. |
|
| Friday, October 26, 2012 - 2:55:27 AM - Raman | Read The Tip |
|
Hi, I would like to know the list of SQL user rights to be given to use the SMO objects. Could you pls help me on this. Thanks |
|
| Friday, December 28, 2012 - 10:33:41 AM - efe | Read The Tip |
|
thanks you so much for this article. |
|
| Saturday, February 02, 2013 - 2:50:31 AM - Amar Patil | Read The Tip |
|
Dear Sir,
DataBase Allready created in this SERVER that time next time same name database created that time how can ? Any idea, Give me ans. my email.ID :- amarpatil.122@gmail.com
Thanks and Regards Amar Patil.
|
|
| Friday, March 08, 2013 - 12:18:21 AM - eskyooel | Read The Tip |
|
Was wondering how I can programmatically get performance metrics for a given sql server instance or database by using SMO (sql management objects). So for example if I want to know things like the CPU usage, I/O writes, etc, which SMO object will give me that?
I've tried using the following but I don't think I'm on the right track.
Server srv = new Server(conn); DataRow[] datarows = srv.EnumPerformanceCounters().Select(); |
|
|
privacy | disclaimer | copyright | advertise | about authors | contribute | feedback | giveaways | user groups Some names and products listed are the registered trademarks of their respective owners. Edgewood Solutions LLC | MSSharePointTips.com | MSSQLTips.com |