如何在不建立订阅的情况下从ReportServer数据库运行报告?

时间:2019-02-07 16:09:57

标签: sql-server tsql reporting-services

我想构建一个后端系统,该系统允许我每晚运行每个报表,然后查询执行日志以查看是否有任何故障。我知道您可以为这些报告建立订阅并定义参数等,但是有没有一种方法可以使用TSQL从ReportServer数据库执行每个报告而无需建立每个订阅?

1 个答案:

答案 0 :(得分:0)

我了解您的总体目标是要使此过程自动化,而不必为每个报告都编写订阅。您说您想在T-SQL中做到这一点,但这是否满足您的总体目标?

如果您接受.Net这样的话,则可以使用System.Data.SqlClient.SqlConnection和相关类查询报表服务器目录并获取所有报表的列表。

然后,您可以使用System.Net.WebClient或类似工具尝试下载报告的pdf。从那里您可以读取执行日志,也可以在.Net代码中捕获错误。

编辑

好吧,既然您接受了答案,并且看来您可能会走这条路,那么我会提到,如果您不熟悉.net,那么对您来说可能是一条漫长的路。以下是一些可以帮助您入门的东西。

下面是一个利用.Net的c#函数,它将查询报表目录。如果safeImmediate设置为true,则将仅捕获可以立即运行的报告,因为其中没有参数,或者默认值覆盖了这些参数。

IEnumerable<string> GetReportPaths(
    string conStr,
    bool safeImmediate // as in, you can exexute the report right away without paramters
) {

    using (var con = new SqlConnection(conStr))
    using (var cmd = new SqlCommand()) {

        cmd.Connection = con;
        cmd.CommandText = @"select path from catalog where type=2";
        con.Open();

        if (safeImmediate) 
            cmd.CommandText = @"

                select      path
                from        catalog 
                cross apply (select 
                                params = convert(xml, Parameter).value('count(Parameters/Parameter)', 'int'),
                                defaults = convert(xml, Parameter).value('count(Parameters/Parameter/DefaultValues/Value)', 'int')
                            ) counts
                where       type = 2  
                and         params = defaults
                and         path not like '%subreport%' -- this is not standard.  Just works for my conventions

            ";

        using (var rdr = cmd.ExecuteReader())
        while (rdr.Read()) 
            yield return rdr["path"].ToString();

    }

}

下一个函数将根据给定的正确路径下载报告:

byte[] DownloadReport (
    WebClient wc, 
    string coreUrl, 
    string fullReportPath, 
    string parameters = "" // you won't use this but may come in handy for other uses
) {
    var pathToViewer = "ReportServer/Pages/ReportViewer.aspx"; // for typical ssrs installs
    var renderOptions = "&rs:Format=pdf&rs:Command=Render"; // return as pdf
    var url = $@"{coreUrl}/{pathToViewer}?{fullReportPath}{parameters}{renderOptions}";
    url = Uri.EscapeUriString(url); // url's don't like certain characters, fix it
    return wc.DownloadData(url); 
}

这利用了上面的功能来找出成功的和不成功的:

    var sqlCon = "Server=yourReportServer; Database=ReportServer; Integrated Security=yes"; // or whatever
    var ssrsSite = "http://www.yourSite.org";

    using (var wc = new WebClient()) {

        wc.UseDefaultCredentials = true; // or whatever

        int loops = 3; // get rid of this when you're ready for prime-time

        foreach(var path in GetReportPaths(sqlCon, true)) {

            try {
                DownloadReport(wc, ssrsSite, path);
                Debug.WriteLine($"Success with: {path}");
            }
            catch(Exception ex) { // you might want to get more specific
                Debug.WriteLine($"Failed with: {path}"); 
            }

            if (loops-- == 0)
                break;

        }

    }

很多东西都可以学习,但这可能是非常有益的。祝你好运。