Мне нужно создать повторяемый процесс для развертывания отчетов служб отчетов SQL Server. Я не сторонник использования Visual Studio и Business Development Studio для этого. Метод rs.exe сценариев развертывания также кажется довольно неуклюжим. У кого-то есть очень элегантный способ, которым они смогли развернуть отчеты. Ключевым моментом здесь является то, что я хочу, чтобы процесс был полностью автоматизирован.
Развертывание служб отчетов
Ответ 1
Мы используем rs.exe, как только мы разработали script, нам больше не нужно было трогать его, он просто работает.
Вот источник (я слегка модифицировал его вручную, чтобы удалить конфиденциальные данные без возможности протестировать его, надеюсь, что я ничего не тормозил), он развертывает отчеты и связанные изображения из поддиректорий для разных языков. Также создается источник данных.
'=====================================================================
' File: PublishReports.rss
'
' Summary: Script that can be used with RS.exe to
' publish the reports.
'
' Rss file spans from beginnig of this comment to end of module
' (except of "End Module").
'=====================================================================
Dim langPaths As String() = {"en", "cs", "pl", "de"}
Dim filePath As String = Environment.CurrentDirectory
Public Sub Main()
rs.Credentials = System.Net.CredentialCache.DefaultCredentials
'Create parent folder
Try
rs.CreateFolder(parentFolder, "/", Nothing)
Console.WriteLine("Parent folder created: {0}", parentFolder)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
PublishLanguagesFromFolder(filePath)
End Sub
Public Sub PublishLanguagesFromFolder(ByVal folder As String)
Dim Lang As Integer
Dim langPath As String
For Lang = langPaths.GetLowerBound(0) To langPaths.GetUpperBound(0)
langPath = langPaths(Lang)
'Create the lang folder
Try
rs.CreateFolder(langPath, "/" + parentFolder, Nothing)
Console.WriteLine("Parent lang folder created: {0}", parentFolder + "/" + langPath)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
'Create the shared data source
CreateDataSource("/" + parentFolder + "/" + langPath)
'Publish reports and images
PublishFolderContents(folder + "\" + langPath, "/" + parentFolder + "/" + langPath)
Next 'Lang
End Sub
Public Sub CreateDataSource(ByVal targetFolder As String)
Dim name As String = "data source"
'Data source definition.
Dim definition As New DataSourceDefinition
definition.CredentialRetrieval = CredentialRetrievalEnum.Store
definition.ConnectString = "data source=" + dbServer + ";initial catalog=" + db
definition.Enabled = True
definition.EnabledSpecified = True
definition.Extension = "SQL"
definition.ImpersonateUser = False
definition.ImpersonateUserSpecified = True
'Use the default prompt string.
definition.Prompt = Nothing
definition.WindowsCredentials = False
'Login information
definition.UserName = "user"
definition.Password = "password"
Try
'name, folder, overwrite, definition, properties
rs.CreateDataSource(name, targetFolder, True, definition, Nothing)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
Public Sub PublishFolderContents(ByVal sourceFolder As String, ByVal targetFolder As String)
Dim di As New DirectoryInfo(sourceFolder)
Dim fis As FileInfo() = di.GetFiles()
Dim fi As FileInfo
Dim fileName As String
For Each fi In fis
fileName = fi.Name
Select Case fileName.Substring(fileName.Length - 4).ToUpper
Case ".RDL"
PublishReport(sourceFolder, fileName, targetFolder)
Case ".JPG", ".JPEG"
PublishResource(sourceFolder, fileName, "image/jpeg", targetFolder)
Case ".GIF", ".PNG", ".BMP"
PublishResource(sourceFolder, fileName, "image/" + fileName.Substring(fileName.Length - 3).ToLower, targetFolder)
End Select
Next fi
End Sub
Public Sub PublishReport(ByVal sourceFolder As String, ByVal reportName As String, ByVal targetFolder As String)
Dim definition As [Byte]() = Nothing
Dim warnings As Warning() = Nothing
Try
Dim stream As FileStream = File.OpenRead(sourceFolder + "\" + reportName)
definition = New [Byte](stream.Length) {}
stream.Read(definition, 0, CInt(stream.Length))
stream.Close()
Catch e As IOException
Console.WriteLine(e.Message)
End Try
Try
'name, folder, overwrite, definition, properties
warnings = rs.CreateReport(reportName.Substring(0, reportName.Length - 4), targetFolder, True, definition, Nothing)
If Not (warnings Is Nothing) Then
Dim warning As Warning
For Each warning In warnings
Console.WriteLine(warning.Message)
Next warning
Else
Console.WriteLine("Report: {0} published successfully with no warnings", targetFolder + "/" + reportName)
End If
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
Public Sub PublishResource(ByVal sourceFolder As String, ByVal resourceName As String, ByVal resourceMIME As String, ByVal targetFolder As String)
Dim definition As [Byte]() = Nothing
Dim warnings As Warning() = Nothing
Try
Dim stream As FileStream = File.OpenRead(sourceFolder + "\" + resourceName)
definition = New [Byte](stream.Length) {}
stream.Read(definition, 0, CInt(stream.Length))
stream.Close()
Catch e As IOException
Console.WriteLine(e.Message)
End Try
Try
'name, folder, overwrite, definition, MIME, properties
rs.CreateResource(resourceName, targetFolder, True, definition, resourceMIME, Nothing)
Console.WriteLine("Resource: {0} with MIME {1} created successfully", targetFolder + "/" + resourceName, resourceMIME)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
Вот пакет для вызова rs.exe:
SET ReportServer=%1
SET DBServer=%2
SET DBName=%3
SET ReportFolder=%4
rs -i PublishReports.rss -s %ReportServer% -v dbServer="%DBServer%" -v db="%DBName%" -v parentFolder="%ReportFolder%" >PublishReports.log 2>&1
pause
Ответ 2
Я использовал script @David, но мне пришлось добавить код (я набираю это как ответ, так как это слишком длинное для комментария.
Проблема заключается в том, что если в определении отчета уже есть "общий источник данных", это никогда не тот же источник данных, что и тот, который создан в script.
Это также становится очевидным из предупреждения, вызванного методом CreateReport:
Набор данных '' относится к общему источнику данных '', который не публикуется на сервере отчетов.
Поэтому источник данных должен быть установлен явно после этого. Я внес следующие изменения кода:
Я добавил глобальную переменную:
Dim dataSourceRefs(0) As DataSource
В конце метода CreateDataSource эта переменная заполняется:
Dim dsr As New DataSourceReference
dsr.Reference = "/" + parentFolder + "/" + db
Dim ds As New DataSource
ds.Item = CType(dsr, DataSourceDefinitionOrReference)
ds.Name = db
dataSourceRefs(0) = ds
И в методе PublishReport этот источник данных становится явно установленным (после вызова CreateReport):
rs.SetItemDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
Обратите внимание, что этот последний вызов - только RS 2005 или выше. Если вы хотите загружать отчеты на сервер RS 2000, вам нужно вместо этого использовать Источники данных Report:
rs.SetReportDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
Ответ 3
Ну не очень изящный. Мы создали собственный инструмент, который использует веб-службу reportingservices2005. Мы обнаружили, что это самый надежный способ получить то, что мы хотим.
Это не так сложно и позволяет вам расширять его, чтобы делать другие вещи, такие как создание источников данных и папок по мере необходимости.
Ответ 4
Я настоятельно рекомендую RSScripter. Как отмечено в обзоре:
Сценарий служб Reporting Services - это .NET. Приложение Windows Forms, которое позволяет сценариев и передачи всех Отчеты Microsoft SQL Server Статьи каталога услуг, которые помогают перенос их с одного сервера на другой. Его также можно легко использовать перемещать элементы по массе из одного отчета Папка служб для другого на том же сервер. В зависимости от сценариев выбранные варианты, службы Reporting Services Скриптер также может передавать весь каталог свойства элемента, такие как Описания, Параметры истории, варианты выполнения (включая отчетный и общий расписания), Подписки (обычные и данные) и отчет на стороне сервера Параметры.
Ответ 5
Я знаю, что вы говорите, что вы не поддерживаете Business Development Studio для этого, но я нашел, что встроенные инструменты очень надежны и просты в использовании.
Ответ 6
Вы изучали любые решения непрерывной интеграции, такие как CruiseControl.NET? Если вы можете развернуть отчеты с помощью rs.exe, тогда вы можете настроить автоматизированный процесс в CruiseControl для создания и развертывания ваших отчетов по таймеру или при каждом изменении отчета.