SQL Server Management Object(SMO)大大簡化數據庫工具的開發 幾行代碼開發功能強大的SQL工具


開發與數據庫有關的程序,經常需要對數據庫進行自動化操作,而不是打開SQL Server Management Studio來寫SQL或是圖形化操作數據,於是需要一個公共類庫,可以處理SQL Server有關的基礎操作,比如連接數據庫,讀取所有的表,修改存儲過程,讀取表的所有字段及其類型。目前為止,我找到以下方法

1  DMO (legacy of SQL Server 2000)

DMO (Interop.SQLDMO.dll) 操作這個程序集,它包含很多基礎的數據庫相關的功能。在SQL Server 2000中,這個程序集的作用很大,非托管代碼,互操作可能會帶來性能損失

2  直接寫SQL腳本(ADO.NET)

用ADOO.NET 發送到SQL Server中,比如下面的存儲過程,可以幫助產生表的結構信息,這個功能常用來產生hotfix的Revised SQL語句

--exec GenerateScript 'Item'
Create Procedure GenerateScript 
(            
    @tableName varchar(100)
)            
as            
If exists (Select * from Information_Schema.COLUMNS where Table_Name= @tableName)            
Begin            
    declare @sql varchar(8000)            
    declare @table varchar(100)            
    declare @cols table (datatype varchar(50))          
    insert into @cols values('bit')          
    insert into @cols values('binary')          
    insert into @cols values('bigint')          
    insert into @cols values('int')          
    insert into @cols values('float')          
    insert into @cols values('datetime')          
    insert into @cols values('text')          
    insert into @cols values('image')          
    insert into @cols values('uniqueidentifier')          
    insert into @cols values('smalldatetime')          
    insert into @cols values('tinyint')          
    insert into @cols values('smallint')          
    insert into @cols values('sql_variant')          
               
    set @sql='' 
               
    Select 
        @sql=@sql+             
        case when charindex('(',@sql,1)<=0 then '(' else '' end +Column_Name + ' ' +Data_Type +             
        case when Data_Type in (Select datatype from @cols) then '' else  '(' end+
        case when data_type in ('real','money','decimal','numeric')  then cast(isnull(numeric_precision,'') as varchar)+','+
        case when data_type in ('real','money','decimal','numeric') then cast(isnull(Numeric_Scale,'') as varchar) end
        when data_type in ('char','nvarchar','varchar','nchar') then cast(isnull(Character_Maximum_Length,'') as varchar)       else '' end+
        case when Data_Type in (Select datatype from @cols)then '' else  ')' end+
        case when Is_Nullable='No' then ' Not null,' else ' null,' end            
    from 
        Information_Schema.COLUMNS where Table_Name=@tableName            
     
      
    select  
        @table=  'Create table ' + table_Name 
    from 
        Information_Schema.COLUMNS 
    where 
        table_Name=@tableName            

    select @sql=@table + substring(@sql,1,len(@sql)-1) +' )'            

    select @sql  as DDL         
      
End            

Else        
    Select 'The table '+@tableName + ' does not exist'           

再比如,要修改數據庫中某些列的排序規則,可以運行下面的腳本

declare @TableName Nvarchar(4000),
    @ColumnName Nvarchar(4000),
    @CharacterMaxLen Nvarchar(4000),
    @CollationName Nvarchar(4000),
    @IsNullable Nvarchar(4000),
    @DataType Nvarchar(4000),
    @SQLText Nvarchar(4000)
 
SET @CollationName = 'SQL_Latin1_General_CP1_CI_AS'
 
declare MyTableCursor cursor for
    SELECT name FROM sys.Tables
 
OPEN MyTableCursor
FETCH NEXT FROM MyTableCursor INTO @TableName
WHILE @@FETCH_STATUS = 0
    BEGIN
        DECLARE MyColumnCursor Cursor
        FOR 
        SELECT COLUMN_NAME,DATA_TYPE, CHARACTER_MAXIMUM_LENGTH,
            IS_NULLABLE from information_schema.columns
            WHERE table_name = @TableName AND  (Data_Type LIKE '%char%' 
            OR Data_Type LIKE '%text%') AND COLLATION_NAME <> @CollationName
            ORDER BY ordinal_position 
        Open MyColumnCursor
 
        FETCH NEXT FROM MyColumnCursor INTO @ColumnName, @DataType, 
              @CharacterMaxLen, @IsNullable
        WHILE @@FETCH_STATUS = 0
            BEGIN
            SET @SQLText = 'ALTER TABLE ' + @TableName + ' ALTER COLUMN [' + @ColumnName + '] ' + 
              @DataType + '(' + CASE WHEN @CharacterMaxLen = -1 THEN 'MAX' ELSE @CharacterMaxLen END + 
              ') COLLATE ' + @CollationName + ' ' + 
              CASE WHEN @IsNullable = 'NO' THEN 'NOT NULL' ELSE 'NULL' END
            PRINT @SQLText 
 
            FETCH NEXT FROM MyColumnCursor INTO @ColumnName, @DataType, 
                  @CharacterMaxLen, @IsNullable
        END
        CLOSE MyColumnCursor
        DEALLOCATE MyColumnCursor
 
FETCH NEXT FROM MyTableCursor INTO @TableName
END
CLOSE MyTableCursor
DEALLOCATE MyTableCursor

通過Google,可以輕松的找到很多這樣的腳本,時間的積累,會增加很多實用的腳本。

如果你不想通過Google,可以采用一個靈活的變通方法,下載一個代碼生成相關的工具軟件,反編譯它的源代碼,你會看到有很多與SQL元數據相關的SQL語句,直接拿來主義就可以了。

說到代碼生成器,Code Smith是很優秀的一個工具,找到它的SchemaProviders目錄,看到有以下幾個程序集文件

image

以我熟悉的SQL Server為例子,來看看它有哪些免費的資源給我們用

image

注意到上圖中所示,Code Smith提供了豐富的SQL元數據腳本,可以減少你很多查找Google的時間。

 

3  SQL Server Management Object (From Microsoft SQL Server,2005/2008/2008 R2/2012)

DMO的托管版本,功能上有很大的增強。SQL Serve的一些工具也是基於這個類庫開發的。

image

每個版本的SQL Server都會伴隨着新的Management Object發布,獨立成一個Windows 組件包。

舉例說明應用SMO是開發SQL Server的工具

SQL Backup and Restore 備份與還原

image

核心源程序代碼

Backup backup = new Backup();
backup.Action = BackupActionType.Database;
backup.Database = “MIS";
BackupDeviceItem backupDeviceItem = new BackupDeviceItem("C:\MIS20130523.bak", DeviceType.File);
backup.Devices.Add(backupDeviceItem);
backup.Initialize = true;
String script = backup.Script(SqlServerSelection);
backup.SqlBackup(SqlServerSelection);

 

SQL Server Document 給SQL對象添加注釋

image

打開一個數據庫表,列舉它的字段,給表或字段添加備注信息,使用extended property完成,核心代碼如下

//更新表的備注信息
 string  updateTableDescription = @"  if(select count(1) from fn_listextendedproperty(N'MS_Description'," +
   "   N'SCHEMA',N'{2}',N'TABLE',N'{0}',NULL,NULL))>0 " +
  "    EXEC sp_updateextendedproperty N'MS_Description',N'{1}', " +
  "    N'SCHEMA',N'{2}', N'TABLE',N'{0}',NULL,NULL  " +
  "   ELSE   " +
 "   EXEC sp_addextendedproperty  N'MS_Description',N'{1}', " +
 "  N'SCHEMA',N'{2}',N'TABLE',N'{0}'   ";

//更新字段的備注信息
 string  updateColumnDescription=@"if(select count(1) from fn_listextendedproperty(N'MS_Description',N'SCHEMA', "+
       " N'{3}',N'TABLE',N'{0}',N'COLUMN', N'{1}'))>0   "+
       " EXEC sp_updateextendedproperty N'MS_Description',N'{2}',  "+
       "    N'SCHEMA',N'{3}', N'TABLE',N'{0}',N'COLUMN', N'{1}'  "+
       "  ELSE   "+
       "  EXEC sp_addextendedproperty  N'MS_Description',N'{2}', "+
        "      N'SCHEMA',N'{3}',N'TABLE',N'{0}',N'COLUMN', N'{1}'   ";

 //讀取表的描述
string getTableDescription = " select value from  " +
        " fn_listextendedproperty(N'MS_Description',N'SCHEMA',N'{1}',N'TABLE'," +
        " N'{0}',NULL, NULL)  ";

//讀取字段的描述
string getColumnDescription=" select objname,value from  "+
        " fn_listextendedproperty(N'MS_Description',N'SCHEMA',N'{1}',N'TABLE',"+
        " N'{0}',N'COLUMN', NULL)  ";
 

如代碼所示,上面4個SQL語句,就是這個軟件的核心代碼。

 

Create Stored Procedures  產生存儲過程的腳本文件

image

當有新的存儲過程要部署給客戶時,不必到SQL Serve 中,只需要用這個小工具,即可產生SQL存儲過程的源代碼

StoredProcedureParameter parm;
StoredProcedure sp=new StoredProcedure(tbl.Parent, procName, spSchema.Name);
sp.TextMode = false
foreach (Column col in tbl.Columns)
{
     if (col.InPrimaryKey == true)
     {
                            // Parameter columns
         parm = new StoredProcedureParameter(sp, "@" + col.Name);
         parm.DataType = col.DataType;
         parm.DataType.MaximumLength= col.DataType.MaximumLength;
         sp.Parameters.Add(parm);
    }
}
sp.Create();
 

同樣的原理,也可以用下面的工具來產生表的創建腳本

image

 

 

Load and Register Assemblies 加載和查看托管程序

image

以托管代碼寫的SQL Server Object(Data type,function stored procedure,trigger)需要以程序集注冊的方式寄宿(host)到SQL Server中,運用這個工具可以以圖形化的界面完成。

SqlAssembly  asm;
asm.Create(new String[] { “C:\ManagedType.dll” });
udf = new UserDefinedFunction(db, "StringToInt32");
udf.TextMode = false;
udf.ImplementationType = ImplementationType.SqlClr;
udf.AssemblyName = "UtilityConversion";
udf.ClassName = "Microsoft.Samples.SqlServer.Conversions";
udf.MethodName = "StringToInt32";
udf.FunctionType = UserDefinedFunctionType.Scalar;
udf.DataType = DataType.Int;
parm = new UserDefinedFunctionParameter(udf, "@Input");
udf.Parameters.Add(parm);
parm.DataType = DataType.NVarChar(255);
udf.Create();
 

Manage Database 管理數據庫

image

可以創建和刪除數據庫,這個小功能在ERP程序中,可以用來創建一個新套帳。

Database db;
string sDatabaseName="MIS";
db = new Database(SqlServerSelection,sDatabaseName);
DataFile  df = new DataFile(fg, sDatabaseName + @"_Data3",
                    SqlServerSelection.Information.MasterDBPath + @"\"
                    + sDatabaseName + @"_Data3" + @".ndf");
db.FileGroups.Add(fg);
LogFile lf = new LogFile(db, sDatabaseName + @"_Log",
                    SqlServerSelection.Information.MasterDBPath + @"\" + sDatabaseName +
                    @"_Log" + @".ldf");
db.LogFiles.Add(lf);

db.Create();

 

Manage Database User 管理數據庫用戶和登陸

image

Database db=new Database("MIS");
User usr = new User(db, "James");
usr.Login = "sa"
usr.Create();

僅僅只有這四句,就可以創建用戶,這個功能可以用來批量管理SQL Server的用戶。

 

SQL Server Services 管理SQL服務實例

image

.NET的服務管理接口可以實現這個功能,不過,這里有更簡潔的方法,核心代碼如下

Service svc;
ManagedComputer mc = new ManagedComputer(SqlServerSelection.Name);
svc=mc.Services[ServicesListView.SelectedItems[0].Text];
svc.Start();

這三行代碼,即可啟動指定的SQL Server服務,API設計的相當簡潔。

 

Connect to SQL Server 連接管理器

image

用這個功能,可以返回能夠連接的SQL Server連接字符串信息,用於程序的業務邏輯功能。

ServerConnection ServerConn = new ServerConnection();
if (WindowsAuthenticationRadioButton.Checked == true)
{
      ServerConn.LoginSecure = true;
}
else
 {
      ServerConn.LoginSecure = false;
      ServerConn.Login = UserNameTextBox.Text;
      ServerConn.Password = PasswordTextBox.Text;
 }

ServerConn.Connect();
 

如果這段代碼沒有拋出異常,表示連接成功,可以依據它返回一個可用的連接字符串。

托管代碼可能效率不高,如果不想依賴於Management Object,可以直接寫SQL腳本,運用ADO.NET技術實現。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM