如何使用 SMO 在 C# 中遍历数据库对象
How to iterate through database objects in C# using SMO
我正在尝试将数据库对象的脚本备份到磁盘。我已经能够将执行此操作的以下代码放在一起,但我必须指定每个对象类型(例如表、函数、存储过程)。
有没有办法在不指定每个集合的情况下循环遍历所有这些对象?
using System;
using System.Data;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using System.IO;
using System.Text;
public static void BackupDB(Server srv, Database db, string savePath)
{
string objPath;
string objFile;
string objTxt;
foreach (StoredProcedure obj in db.StoredProcedures)
{
if (obj.IsSystemObject == false)
{
objPath = savePath + "Stored Procedures\";
Directory.CreateDirectory(objPath);
objFile = objPath + obj.Schema + "." + obj.Name + ".sql";
objTxt = GetScriptString(srv, obj);
File.WriteAllText(objFile, objTxt);
}
}
foreach (Table obj in db.Tables)
{
if (obj.IsSystemObject == false)
{
objPath = savePath + "Tables\";
Directory.CreateDirectory(objPath);
objFile = objPath + obj.Schema + "." + obj.Name + ".txt";
objTxt = GetScriptString(srv, obj);
File.WriteAllText(objFile, objTxt);
}
}
static private string GetScriptString(Server server, SqlSmoObject obj)
{
StringBuilder output = new StringBuilder();
Scripter scr = new Scripter(server);
var script = scr.EnumScript(new SqlSmoObject[] { obj });
foreach (var line in script)
{
output.AppendLine(line);
}
return output.ToString();
}
编辑:
使用 Grant Winney 的回答,我能够将以下方法放在一起以遍历所有对象而不重复行:
public static void BackupDB(Server srv, Database db, string savePath)
{
string objPath;
string objFile;
string objTxt;
Dictionary<string, IEnumerable<ScriptSchemaObjectBase>> dboDict =
new Dictionary<string, IEnumerable<ScriptSchemaObjectBase>>();
dboDict.Add("Stored Procedures", db.StoredProcedures.Cast<StoredProcedure>().Where(x => !x.IsSystemObject));
dboDict.Add("Functions", db.UserDefinedFunctions.Cast<UserDefinedFunction>().Where(x => !x.IsSystemObject));
dboDict.Add("Tables", db.Tables.Cast<Table>().Where(x => !x.IsSystemObject));
dboDict.Add("Views", db.Views.Cast<View>().Where(x => !x.IsSystemObject));
foreach (KeyValuePair<string, IEnumerable<ScriptSchemaObjectBase>> dict in dboDict)
{
IEnumerable<ScriptSchemaObjectBase> dboObjects = dict.Value;
objPath = savePath + dict.Key + "\";
Directory.CreateDirectory(objPath);
foreach (ScriptSchemaObjectBase obj in dboObjects)
{
objFile = objPath + obj.Schema + "." + obj.Name + ".sql";
objTxt = GetScriptString(srv, obj);
File.WriteAllText(objFile, objTxt);
}
}
}
将相似的代码移到单独的方法中,并利用每个 classes 实现相同基础 class 的事实,即 Schema
和 Name
位于。
您可以先使用 LINQ 过滤项目,然后将过滤后的列表传递给其他方法。
public static void BackupDB(Server srv, Database db, string savePath)
{
string objPath;
string objFile;
string objTxt;
BackupObjects(db.StoredProcedures.Cast<StoredProcedure>().Where(x => !x.IsSystemObject));
BackupObjects(db.Tables.Cast<Table>().Where(x => !x.IsSystemObject));
}
private static void BackupObjects(IEnumerable<ScriptSchemaObjectBase> objects)
{
foreach (ScriptSchemaObjectBase obj in objects)
{
objPath = savePath + "Stored Procedures\";
Directory.CreateDirectory(objPath);
objFile = objPath + obj.Schema + "." + obj.Name + ".sql";
objTxt = GetScriptString(srv, obj);
File.WriteAllText(objFile, objTxt);
}
}
我正在尝试将数据库对象的脚本备份到磁盘。我已经能够将执行此操作的以下代码放在一起,但我必须指定每个对象类型(例如表、函数、存储过程)。
有没有办法在不指定每个集合的情况下循环遍历所有这些对象?
using System;
using System.Data;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using System.IO;
using System.Text;
public static void BackupDB(Server srv, Database db, string savePath)
{
string objPath;
string objFile;
string objTxt;
foreach (StoredProcedure obj in db.StoredProcedures)
{
if (obj.IsSystemObject == false)
{
objPath = savePath + "Stored Procedures\";
Directory.CreateDirectory(objPath);
objFile = objPath + obj.Schema + "." + obj.Name + ".sql";
objTxt = GetScriptString(srv, obj);
File.WriteAllText(objFile, objTxt);
}
}
foreach (Table obj in db.Tables)
{
if (obj.IsSystemObject == false)
{
objPath = savePath + "Tables\";
Directory.CreateDirectory(objPath);
objFile = objPath + obj.Schema + "." + obj.Name + ".txt";
objTxt = GetScriptString(srv, obj);
File.WriteAllText(objFile, objTxt);
}
}
static private string GetScriptString(Server server, SqlSmoObject obj)
{
StringBuilder output = new StringBuilder();
Scripter scr = new Scripter(server);
var script = scr.EnumScript(new SqlSmoObject[] { obj });
foreach (var line in script)
{
output.AppendLine(line);
}
return output.ToString();
}
编辑: 使用 Grant Winney 的回答,我能够将以下方法放在一起以遍历所有对象而不重复行:
public static void BackupDB(Server srv, Database db, string savePath)
{
string objPath;
string objFile;
string objTxt;
Dictionary<string, IEnumerable<ScriptSchemaObjectBase>> dboDict =
new Dictionary<string, IEnumerable<ScriptSchemaObjectBase>>();
dboDict.Add("Stored Procedures", db.StoredProcedures.Cast<StoredProcedure>().Where(x => !x.IsSystemObject));
dboDict.Add("Functions", db.UserDefinedFunctions.Cast<UserDefinedFunction>().Where(x => !x.IsSystemObject));
dboDict.Add("Tables", db.Tables.Cast<Table>().Where(x => !x.IsSystemObject));
dboDict.Add("Views", db.Views.Cast<View>().Where(x => !x.IsSystemObject));
foreach (KeyValuePair<string, IEnumerable<ScriptSchemaObjectBase>> dict in dboDict)
{
IEnumerable<ScriptSchemaObjectBase> dboObjects = dict.Value;
objPath = savePath + dict.Key + "\";
Directory.CreateDirectory(objPath);
foreach (ScriptSchemaObjectBase obj in dboObjects)
{
objFile = objPath + obj.Schema + "." + obj.Name + ".sql";
objTxt = GetScriptString(srv, obj);
File.WriteAllText(objFile, objTxt);
}
}
}
将相似的代码移到单独的方法中,并利用每个 classes 实现相同基础 class 的事实,即 Schema
和 Name
位于。
您可以先使用 LINQ 过滤项目,然后将过滤后的列表传递给其他方法。
public static void BackupDB(Server srv, Database db, string savePath)
{
string objPath;
string objFile;
string objTxt;
BackupObjects(db.StoredProcedures.Cast<StoredProcedure>().Where(x => !x.IsSystemObject));
BackupObjects(db.Tables.Cast<Table>().Where(x => !x.IsSystemObject));
}
private static void BackupObjects(IEnumerable<ScriptSchemaObjectBase> objects)
{
foreach (ScriptSchemaObjectBase obj in objects)
{
objPath = savePath + "Stored Procedures\";
Directory.CreateDirectory(objPath);
objFile = objPath + obj.Schema + "." + obj.Name + ".sql";
objTxt = GetScriptString(srv, obj);
File.WriteAllText(objFile, objTxt);
}
}