Using a source script component in SSIS, I am attempting to retreive details of all objects which depend on a table. So far, I have the object type and name but can't retreive the schema. Does anyone know how to acheive this in SMO?
My script component code is:
' Microsoft SQL Server Integration Services user script component
' This is your new script component in Microsoft Visual Basic .NET
' ScriptMain is the entrypoint class for script components
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports Microsoft.SqlServer.Management.Smo
Imports Microsoft.SqlServer.Management.Common
Public Class ScriptMain
Inherits UserComponent
Public Overrides Sub CreateNewOutputRows()
'
'
'
Dim TargetSQLServer As Server
Dim TargetDatabase As Database
Dim TargetTable As Table
Dim uc As New UrnCollection()
Dim dw As New DependencyWalker
Dim dt As DependencyTree
Dim dc As DependencyCollection
Dim dcn As DependencyCollectionNode
Dim sp As New Scripter
Dim outputString As String
TargetSQLServer = New Server("localhost")
TargetDatabase = TargetSQLServer.Databases("AdventureWorks")
For Each TargetTable In TargetDatabase.Tables
' Exclude these objects
If TargetTable.IsSystemObject = False Then
uc = New UrnCollection()
uc.Add(TargetTable.Urn)
sp = New Scripter
sp.Server = TargetSQLServer
' Get dependencies
dw = New DependencyWalker
dw.Server = TargetSQLServer
dt = dw.DiscoverDependencies(uc, DependencyType.Children)
sp = New Scripter(TargetSQLServer)
dc = New DependencyCollection
dc = sp.WalkDependencies(dt)
outputString = ""
For Each dcn In dc
Me.Output0Buffer.AddRow()
Me.Output0Buffer.Database = TargetDatabase.Name.ToString
Me.Output0Buffer.Table = TargetTable.Name.ToString
outputString = dcn.Urn.ToString
Me.Output0Buffer.Dependency.AddBlobData(Text.Encoding.GetEncoding(1252).GetBytes(outputString))
Me.Output0Buffer.ObjectType = dcn.Urn.Type.ToString
outputString = dcn.Urn.GetNameForType(dcn.Urn.Type.ToString).ToString
Me.Output0Buffer.ObjectName.AddBlobData(Text.Encoding.GetEncoding(1252).GetBytes(outputString))
outputString = ""
Me.Output0Buffer.Schema.AddBlobData(Text.Encoding.GetEncoding(1252).GetBytes(outputString))
Next
End If
Next
End Sub
End Class
Hey ekoner,
I have working code that walks the dependency tree in databases, and resolved the issue with simple string parsing.
Your urn will be returned is in the form of
///StoredProcedure[#Name='uspUpdateEmployeeHireInfo' and #Schema='HumanResources']
Just parse for #Name and then for #Schema.
Download the source code for DBSourceTools : http://dbsourcetools.codeplex.com
Have a look at DBSourceToolsLib.SysObjects.UrnParser
And also DBSourceToolsLib.SysObjects.SODependencyTree for working examples.
Related
I am trying to get some data from an API, using an SSIS Script Task with Visual Basic code. But I having some problems because I have Portuguese special characters in some fields. I was trying to solve my problems and I read that this could be achieved by enconding the data. I try to do this with any sucess.
Can anyone help me?
Regards
Using c As WebClient = New WebClient()
c.BaseAddress = URL
c.Headers(HttpRequestHeader.Authorization) = "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(key & ":" & pass))
c.Credentials = New NetworkCredential(key, pass)
Dim xml = c.DownloadString(URL & "CRUser?start=0&count=999&language=English")
'Parse para objetos
Dim doc = XDocument.Parse(xml)
Dim reader = doc.CreateReader()
Dim xRoot As XmlRootAttribute = New XmlRootAttribute()
xRoot.ElementName = "array"
xRoot.IsNullable = True
Dim xmls As New XmlSerializer(GetType(List(Of CRUser)), xRoot)
Dim _data As List(Of CRUser) = xmls.Deserialize(reader)
For Each item As CRUser In _data
'Console.WriteLine(item.id)
'Console.WriteLine(item.firstName)
'..... resto campos injetar no pipelino do SSIS os dados
MyOutputBuffer.AddRow()
MyOutputBuffer.id = item.id
MyOutputBuffer.firstName = item.firstName
Next
End Using
Im doing a webform in vb.net I'm consuming a webservice, Which returns me to all the countries
Only have 1 button Enviar that calls the countries.
Imports service_country = WebServiceVB2.country
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim serv_country As New service_country.country '--Create object'
Dim MyDoc As New System.Xml.XmlDocument
Dim MyXml As String = serv_country.GetCountries() '--Execute procedure from webservice'
MyDoc.LoadXml(MyXml) '--Read Myxml and convert to XML'
Dim SymbolText As String = MyDoc.SelectSingleNode("//NewDataSet/Table/Name").InnerText '--select the node'
Label1.Text = SymbolText
End Sub
My question is How can I select all the values that are inside the 'name'.
Actually it only shows one.
For Example:
Thanks in advance.
This was an interesting problem. Since data is coming as a webpage the open bracket was coming as "& l t ;" while the closing bracket was coming as "& g t ;". So these had to be replaced. I used xml linq to get the names :
Imports System.Xml
Imports System.Xml.Linq
Module Module1
Const URL As String = "http://www.webservicex.net/country.asmx/GetCountries"
Sub Main()
Dim doc1 As XDocument = XDocument.Load(URL)
Dim docStr As String = doc1.ToString()
docStr = docStr.Replace(">", ">")
docStr = docStr.Replace("<", "<")
Dim doc2 As XDocument = XDocument.Parse(docStr)
Dim root As XElement = doc2.Root
Dim defaultNs As XNamespace = root.GetDefaultNamespace()
Dim names() As String = doc2.Descendants(defaultNs + "Name").Select(Function(x) CType(x, String)).ToArray()
End Sub
End Module
Using WebUtility
Imports System.Xml
Imports System.Xml.Linq
Imports System.Text
Imports System.Net
Module Module1
Const URL As String = "http://www.webservicex.net/country.asmx/GetCountries"
Sub Main()
Dim xReader As XmlReader = XmlTextReader.Create(URL)
xReader.MoveToContent()
Dim doc As XDocument = XDocument.Parse(WebUtility.HtmlDecode("<?xml version=""1.0"" encoding=""iso-8859-9"" ?>" & xReader.ReadOuterXml))
Dim root As XElement = doc.Root
Dim defaultNs As XNamespace = root.GetDefaultNamespace()
Dim names() As String = doc.Descendants(defaultNs + "Name").Select(Function(x) CType(x, String)).ToArray()
End Sub
End Module
I am wondering if it is possible to have VBA (Access) open a TFS Bug report webpage and fill in the description ?
While I am able to open the page I have not yet found a way to populate the description and potently other fields.
Perhaps one of the experts knows?
I wouldn't try to do what you are working on.
One, trusting a buggy application to correctly report its own bugs isn't a great idea. But beyond that you will be trying to attach Access to TFS.
That being said you can do this entirely automated. Put in some error trapping and then what you are looking to do is how to call TFS APIs. But you may or may not have to install some third part tools etc.
Starting point TFS API
The way I finally did it is to use a dll to interface between access and tfs...
For anyone trying to do the same here is the code...
Imports Microsoft.TeamFoundation.Client
Imports Microsoft.TeamFoundation.WorkItemTracking.Client
Imports Microsoft.TeamFoundation.WorkItemTracking.Common
Imports System.Runtime.InteropServices
<ComClass(TFSInterOp.ClassId, TFSInterOp.InterfaceId, TFSInterOp.EventsId)> Public Class TFSInterOp
Public Const ClassId As String = "14306fc5-1492-42d6-a032-bc4348508dd3"
Public Const InterfaceId As String = "288339cb-0c2e-45fd-8005-e5fed401f0cc"
Public Const EventsId As String = "723327dc-7777-44e4-b291-9299027665eb"
Public Sub New()
End Sub
Public Function InsertBugWorkItem(Title As String, Desc As String) As String
Dim tfsServer As String = My.Settings("TfsFullPath").ToString ' {YOUR TFS SERVER PATH}
Dim strAssUser As String = My.Settings("AssignTo").ToString
Dim teamFoundationServer1 As Microsoft.TeamFoundation.Client.TfsTeamProjectCollection = Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory.GetTeamProjectCollection(New Uri(tfsServer))
Dim workItemStore1 As New WorkItemStore(teamFoundationServer1)
teamFoundationServer1.Authenticate()
Dim WorkItemStore As WorkItemStore = New WorkItemStore(tfsServer)
Dim tfsProject As Project = WorkItemStore.Projects(0)
Dim wIType As WorkItemType = tfsProject.WorkItemTypes("Bug")
Dim workItem As WorkItem = New WorkItem(wIType)
Dim wiStore = teamFoundationServer1.GetService(Of WorkItemStore)()
Dim Project = wiStore.Projects
Dim Area = Project.Item(0).AreaRootNodes("BITS").Id ' The project to add the work item to
' Prefill items
workItem.Title = Title
workItem.Description = Desc
workItem.AreaId = Project.Item(0).AreaRootNodes("BITS").Id
workItem.Fields("Assigned To").Value = strAssUser
workItem.Fields("System Info").Value = "Access V 1.1.25"
workItem.Fields("Repro Steps").Value = Desc
Dim result As ArrayList = workItem.Validate()
If result.Count > 0 Then
Return (result(0).ToString + "There was an error adding this work item to the work item repository")
Else
workItem.Save()
End If
' Open the new item in explorer
Dim myService = teamFoundationServer1.GetService(Of TswaClientHyperlinkService)()
Dim myUrl = myService.GetWorkItemEditorUrl(workItem.Id)
Dim oProcess As New System.Diagnostics.Process()
oProcess.StartInfo.FileName = myUrl.ToString
oProcess.Start()
Return "OK"
End Function
End Class
I have an SSIS package that is now failing with an error of "index was outside the bounds of an array." It is occuring in the script component task, but I can't see any further information in the log about what line it failed. Here is the text to my Script Component, can anyone see anything wrong with this? I haven't change anything in the package and it just started failing all of a sudden.
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
<Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute> _
<CLSCompliant(False)> _
Public Class ScriptMain
Inherits UserComponent
' Wrapper for web service
'Private CurrencyInfo As RetrieveExchangeRatesOutputMessageContract
' wrapper for Response from web service
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Try
Dim ws As New CurrencyExchangeWS.CurrencyExchangeWS
Dim inContract As New CurrencyExchangeWS.ExchangeRateInputDataContract
Dim msg As New CurrencyExchangeWS.RetrieveExchangeRatesInputMessageContract
Dim inContracts(1) As CurrencyExchangeWS.ExchangeRateInputDataContract
'Dim dt As Date = Now
'dt = dt.AddDays(-1)
inContract.RequestAsOfDate = Now
'inContract.RequestAsOfDate = "2011-07-18"
' IMPORTANT: You need to specify SourceCurrencyIdSpecified and TargetCurrencyIdSpecified or the service will assume these values are null.
inContract.SourceCurrencyIdSpecified = True
inContract.SourceCurrencyId = Row.CurrencyTypeId
inContract.TargetCurrencyIdSpecified = True
inContract.TargetCurrencyId = 47
inContracts(0) = inContract
msg.ExchangeRateInputCollection = inContracts
ws.Credentials = System.Net.CredentialCache.DefaultCredentials
Dim outMsg As CurrencyExchangeWS.RetrieveExchangeRatesOutputMessageContract = ws.RetrieveExchangeRates(msg)
'Dim rate =outMsg.ExchangeRateInfoCollection(0).Rate
Dim rate As Decimal = outMsg.ExchangeRateInfoCollection(0).Rate
'Dim edate = outMsg.ExchangeRateInfoCollection(0).RequestAsOfDate
Dim edate = outMsg.ExchangeRateInfoCollection(0).RateAsOfDate
'Dim edate As DateTime
'edate = outMsg.ExchangeRateInfoCollection(0).RateAsOfDate
Row.date = edate
Row.rate = Convert.ToDecimal(1.0 / rate)
'Dim currency = outMsg.ExchangeRateInfoCollection(0).TargetCurrencyId
Catch ex As Exception
ComponentMetaData.FireError(1, ComponentMetaData.Name, ex.Message, String.Empty, 0, True)
End Try
End Sub
Public Overrides Sub PreExecute()
MyBase.PreExecute()
'
' Add your code here for preprocessing or remove if not needed
''
End Sub
Public Overrides Sub PostExecute()
MyBase.PostExecute()
'
' Add your code here for postprocessing or remove if not needed
' You can set read/write variables here, for example:
' Me.Variables.MyIntVar = 100
''
End Sub
'Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
'
' Add your code here
'
'End Sub
End Class
At first glance, the most likely culprit is that outMsg.ExchangeRateInfoCollection contains zero items. Unfortunately, we don't have enough information to say that for sure. One possible way to get that additional information is to declare a progress string variable outside your Try ... Catch block, update it before each step in your code, and include it in the FireError message:
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim progress As String
Try
Dim ws As New CurrencyExchangeWS.CurrencyExchangeWS
Dim inContract As New CurrencyExchangeWS.ExchangeRateInputDataContract
Dim msg As New CurrencyExchangeWS.RetrieveExchangeRatesInputMessageContract
Dim inContracts(1) As CurrencyExchangeWS.ExchangeRateInputDataContract
progress = "Setting inContract.RequestAsOfDate"
inContract.RequestAsOfDate = Now
progress = "Setting inContract.SourceCurrencyIdSpecified"
inContract.SourceCurrencyIdSpecified = True
' etc, etc, etc.
Dim outMsg As CurrencyExchangeWS.RetrieveExchangeRatesOutputMessageContract
progress = "Setting outMsg"
outMsg = ws.RetrieveExchangeRates(msg)
progress = String.Format("Setting rate; outMsg.ExchangeRateInfoCollection.Length is {0}", outMsg.ExchangeRateInfoCollection.Length)
' This is likely the place where the IndexOutOfRangeException is being thrown
Dim rate As Decimal = outMsg.ExchangeRateInfoCollection(0).Rate
' rest of code
Catch ex As Exception
ComponentMetaData.FireError(1, ComponentMetaData.Name, progress + ": " + ex.Message, String.Empty, 0, True)
End Try
End Sub
I am trying to write a VBA script which imports all of the Excel files in a folder into a table in Access 2003, first checking if they have been imported or not. That part is fine. The issue I run into is clearing out some of the formulas that don't get used on the spreadsheet which causes difficulty when Access tries to import the range. when running the code as-is, I get an error "User-defined type not defined".
I am using late binding since I am developing for a site that uses multiple versions of Office and therfore can't reference the same library using early binding. The problem code is below:
Private Sub Command2_Click()
'Declare Variables
Dim xlApp As Object
Dim xlBook As Object
Dim LSQL As String
Dim SkippedCounter As Integer
Dim ImportedCounter As Integer
Dim BUN As Long
Dim SubmitDate As Date
Dim LSQL2 As String
Dim LSQL3 As String
'Start counters for final notice
SkippedCounter = 0
ImportedCounter = 0
Dim myDir As String, fn As String
'Set directory for importing files
myDir = "U:\Five Star\Operations\restore\Surveys\My InnerView - 2010\Action plans\Action plans - input for DB\"
'Function for selecting files in folder
fn = Dir(myDir & "*.xls")
'Determine if there are files in side the folder
If fn = "" Then
MsgBox "Folder is Empty!"
Else
'Begin cycling through files in the folder
Do While fn <> ""
'Create new Excel Object
Set xlApp = CreateObject("Excel.Application")
'Make it appear on the screen while importing
xlApp.Visible = True
'Open the workbook at hand
Set xlBook = xlApp.Workbooks.Open(myDir & fn)
'Check to see if it has been imported already
If xlBook.Sheets("Action plan form").Range("A1").Value = "Imported" Then
'If it has been imported, add 1 to the counter, close the file and close the instance of Excel
SkippedCounter = SkippedCounter + 1
xlBook.Close
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
Else
'Otherwise, unprotect the worksheet
xlBook.UnProtect Password:="2010"
Dim c As Range
'Unhide worksheet needed and clean it up
xlBook.Sheets("Action plan DB data").Visible = True
xlBook.Sheets("Action plan DB data").Range("B10:O10").ClearFormats
xlBook.Sheets("Action plan DB data").Range("N11:N84").ClearFormats
For Each c In xlBook.Sheets("Action plan DB data").Range("DB_import")
If c.Value = "" Or c.Value = 0 Then c.Clear
Next c
...
The rest of the code should run fine, it jsut has an issue with the declaration of "range" and looping through it. Thanks for your help!
Remove As Range from Dim c As Range and that will make c into an object. That way when it gets late-bound to a range you won't have any issues.