我想构建一个后端系统,该系统允许我每晚运行每个报表,然后查询执行日志以查看是否有任何故障。我知道您可以为这些报告建立订阅并定义参数等,但是有没有一种方法可以使用TSQL从ReportServer数据库执行每个报告而无需建立每个订阅?
答案 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;
}
}
很多东西都可以学习,但这可能是非常有益的。祝你好运。