【问题标题】:How to iterate through database objects in C# using SMO如何使用 SMO 遍历 C# 中的数据库对象
【发布时间】:2016-03-09 22:47:35
【问题描述】:

我正在尝试将我的数据库对象的脚本备份到磁盘。我已经能够将执行此操作的以下代码放在一起,但我必须指定每个对象类型(例如表、函数、存储过程)。

有没有办法在不指定每个集合的情况下遍历所有这些对象?

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();
}

编辑: 使用格兰特温尼的回答,我能够将下面的方法放在一起,在不重复行的情况下遍历所有对象:

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);
        }
    }

}

【问题讨论】:

    标签: c# smo


    【解决方案1】:

    将相似的代码移到单独的方法中,并利用这些类中的每一个都实现相同的基类这一事实,这是SchemaName 所在的位置。

    您可以先使用 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);
        }
    }
    

    【讨论】:

    • 感谢您的帮助。我是 Enums 和 LINQ 的菜鸟,但使用它我能够得到一些工作(见我的编辑)。我仍然觉得我通过单独添加每个 DB 对象来重复行,但同样,我不是 100% 了解像这样的枚举是如何工作的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多