C# 如何从多个服务器/数据库中查找相同、修改过且唯一的SQL对象?

C# 如何从多个服务器/数据库中查找相同、修改过且唯一的SQL对象?,c#,sql,sql-server,smo,ssms-2017,C#,Sql,Sql Server,Smo,Ssms 2017,问题摘要: 我们在多个服务器上有一组数据库,它们“应该”都具有相同的SQL对象。多年来,我们的开发人员在各种数据库中添加/修改了对象,使它们不再匹配。我需要从多个服务器上完全相同的多个数据库中获取所有SQL对象(表、视图、存储过程、用户定义函数)的列表。(稍后获取唯一项目列表,稍后获取修改项目列表)。我目前的解决方案有效,但速度相当慢。我想知道是否有更好的替代方案,但我找不到 当前解决方案: 目前,我一直在使用C#中的SMO获取所有对象的URN并编写脚本。当我试图一次编写一个对象的脚本时,过程很

问题摘要:

我们在多个服务器上有一组数据库,它们“应该”都具有相同的SQL对象。多年来,我们的开发人员在各种数据库中添加/修改了对象,使它们不再匹配。我需要从多个服务器上完全相同的多个数据库中获取所有SQL对象(表、视图、存储过程、用户定义函数)的列表。(稍后获取唯一项目列表,稍后获取修改项目列表)。我目前的解决方案有效,但速度相当慢。我想知道是否有更好的替代方案,但我找不到

当前解决方案:

目前,我一直在使用C#中的SMO获取所有对象的URN并编写脚本。当我试图一次编写一个对象的脚本时,过程很慢(对服务器的大量调用)。如果我尝试通过将它们的URN打包到一个数组中来编写脚本,过程会更快,但我只得到结果脚本的可枚举或StringCollection,而没有组织脚本来自哪个对象等。有什么更好的方法来实现这一点(我知道现有的工具,如ApexSQL或RedGate,它们目前是不可能的)。我目前的解决方案是按名称对它们进行分组(并按服务器划分),然后在那些较小的按名称批中编写脚本

请原谅我目前的代码,我一直在各地尝试不同的方法。也许有一种解决方案甚至不需要分析代码。需要注意两件事:

  • 我有一个名为SqlObjectInfo的类,它只存储每个对象的一些基本信息,例如:名称、服务器、数据库、模式、类型、Urn
  • items是一个SqlObjectInfo集合,它是一个包含SqlObjectInfo列表以及一些帮助函数的类,用于添加服务器和数据库中的对象。使用所有SqlObjectInfo填充此集合速度很快,因此这不是问题所在
  • //创建数据表
    var表=新数据表(“相等对象”);
    表.列.添加(“名称”);
    表.列.添加(“类型”);
    //创建数据行
    int dbCount=items.SqlObjects.GroupBy(obj=>obj.Database.Count();
    DMP DMP=DiffMatchPatchModule.Default;
    var rows=新列表();
    foreach(items.SqlObjects.GroupBy(obj=>obj.Name)中的igroupingnamegroup)
    {
    var likamedobjs=nameGroup.ToList();
    if(likamedobjs.Count!=dbCount)
    {
    continue;//对象不在所有数据库中
    }
    //脚本对象
    var rawScripts=新列表();
    bool scriptingSucceeded=true;
    foreach(nameGroup.GroupBy(obj=>obj.Server)中的igroupingservergroup)
    {
    Server=serverGroup.Key;
    Urn[]urns=serverGroup.Select(obj=>obj.Urn.ToArray();
    var scripter=新脚本编写器(服务器)
    {
    选项=项。脚本选项
    };
    i数不清的结果;
    尝试
    {
    结果=scripter.EnumScript(urns);
    }
    捕获(失败操作异常)
    {
    scriptingSucceeded=false;
    break;//对象可能已加密
    }
    rawScripts.AddRange(结果);
    }
    如果(!scriptingsucceed)
    {
    继续;
    }
    如果(rawScripts.Count%nameGroup.Count()!=0)
    {
    继续;
    }
    var allScripts=new List();
    int stringsPerScript=rawScripts.Count/nameGroup.Count();
    对于(inti=0;idiff.Operation.IsEqual))
    {
    allEqual=假;
    break;//脚本不相等
    }
    }
    //如果所有脚本都相等,则为对象创建数据行
    如果(allEqual)
    {
    DataRow行=table.NewRow();
    行[“名称”]=LIKEAMEDOBJS[0]。名称;
    行[“类型”]=LikeAmedobjs[0]。类型;
    行。添加(行);
    }
    }
    //将数据行添加到数据表
    foreach(rows.OrderBy中的DataRow行(r=>r[“Type”])。然后是by(r=>r[“Name”]))
    {
    table.Rows.Add(行);
    }
    //将数据表写入csv
    var builder=新的StringBuilder();
    AppendLine(string.Join(“,”,table.Columns.Cast().Select(col=>col.ColumnName));
    foreach(table.Rows中的DataRow行)
    {
    AppendLine(string.Join(“,”,row.ItemArray.Select(field=>field.ToString());
    }
    writealText(“equalObjects.csv”,builder.ToString());
    

    代码运行正常。我可以得到预期的csv文件(名称|类型)在多个服务器上的所有数据库中,所有对象都完全相同。速度太慢了。我的方法正确吗?有更好/更现代的解决方案吗?

    所有数据库中都有表具有对象。在sqlserver中,它是sysobj。首先需要创建一个主列表。您可以从.all d合并此视图然后将其连接到每个db sysobj