(this is also on StackOverflow at http://stackoverflow.com/questions/41046444/ssis-programmatic-package-validate-run-issue)
Hi All,
I am trying to create a simple SSIS task to load data from a SQL Server table (with one int column called [num]) to an Oracle table (with one NUMBER column called [ID]) via the .NET Interop assemblies for SSIS. I can create the package and save it to a DTSX
file, however when I run (either programmatically or via dtexec), it fails. I'm following the dev guide for programmatically creating packages, and when I poke around at the properties of the various objects nothing really jumps out at me.
As a secondary issue, I see there is a Package.Validate method available but I have no idea how to call it (there are arguments and return values required). When I run the package via dtexec it does validation and provides somewhat useful validation errors,
so I'm hoping to be able to hook into that programatically.
The validation error I get is:
Error: 2016-12-08 09:39:15.96
Code: 0xC004706B
Source: {A8E8D1A6-3826-4222-B6DC-46008A1722DF} SSIS.Pipeline
Description: "OLE DB Destination" failed validation and returned validation status "VS_NEEDSNEWMETADATA".
From what I can tell online, the cause of this error is bad column mappings, however I've lifted the code more or less straight from the dev guide.
So my two questions are:
1. How can I troubleshoot this validation error VS_NEEDSNEWMETADATA, preferably programatically?
2. How can I call Package.Validate in order to get such validation errors programatically?
Any help is appreciated!
Full code listing (I run this in C# Interactive using Visual Studio, no exceptions are thrown, but result ends up with a value of Failure):
// these are just adding references to the context:
#r "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.DTSPipelineWrap\v4.0_11.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.DTSPipelineWrap.dll"
#r "C:\Windows\Microsoft.NET\assembly\GAC_64\Microsoft.SqlServer.DTSRuntimeWrap\v4.0_11.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.DTSRuntimeWrap.dll"
#r "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.ManagedDTS\v4.0_11.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.ManagedDTS.dll"
#r "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.PipelineHost\v4.0_11.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.PipelineHost.dll"
#r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.dll"
#r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll"
#r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Xml.Linq.dll"
#r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.DataSetExtensions.dll"
#r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Microsoft.CSharp.dll"
#r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll"
#r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Net.Http.dll"
#r "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Xml.dll"
// the actual code:
using dtsrt = Microsoft.SqlServer.Dts.Runtime;
using dtsp = Microsoft.SqlServer.Dts.Pipeline;
using dtspw = Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using refl = System.Reflection;
private string GetHresultSymbolicName(int errorCode)
{
dtsrt.HResults hresults = new Microsoft.SqlServer.Dts.Runtime.HResults();
return (from refl.FieldInfo fi in hresults.GetType().GetFields() where (((int)fi.GetValue(hresults)) == errorCode) select fi.Name).Single();
}
// base setup
dtsrt.Package package = new dtsrt.Package();
dtsrt.Executable e = package.Executables.Add("STOCK:PipelineTask");
dtsrt.TaskHost thMainPipe = e as dtsrt.TaskHost;
dtspw.MainPipe dataFlowTask = thMainPipe.InnerObject as dtspw.MainPipe;
dtsrt.Application app = new Microsoft.SqlServer.Dts.Runtime.Application();
dtsrt.PipelineComponentInfos componentInfos = app.PipelineComponentInfos;
// source connection
dtsrt.ConnectionManager srcConnectionManager = package.Connections.Add("OLEDB");
srcConnectionManager.Name = "Source OLEDB Connection";
srcConnectionManager.ConnectionString = "Provider=SQLOLEDB; Address=XXX; Database=Sandbox; Trusted_Connection=yes;";
// dest connection
dtsrt.ConnectionManager destConnectionManager = package.Connections.Add("OLEDB");
destConnectionManager.Name = "Destination OLEDB Connection";
destConnectionManager.ConnectionString = "Provider=OraOLEDB.Oracle; Data Source=XXX;User Id=SANDBOX;Password=123456;";
// thanks: ole.OleDbDataReader rdr = ole.OleDbEnumerator.GetRootEnumerator();
// dest component
dtspw.IDTSComponentMetaData100 destComponent = dataFlowTask.ComponentMetaDataCollection.New();
destComponent.ComponentClassID = "DTSAdapter.OLEDBDestination.3";
destComponent.Instantiate();
dtspw.CManagedComponentWrapper destWrapper = destComponent.Instantiate();
destWrapper.ProvideComponentProperties();
destComponent.RuntimeConnectionCollection[0].ConnectionManager = dtsrt.DtsConvert.GetExtendedInterface(destConnectionManager);
destComponent.RuntimeConnectionCollection[0].ConnectionManagerID = destConnectionManager.ID;
destComponent.CustomPropertyCollection["CommandTimeout"].Value = 0; // no timeout
destComponent.CustomPropertyCollection["AccessMode"].Value = 2; // sqlcommand
destComponent.CustomPropertyCollection["SqlCommand"].Value = "select * from my_asdf";
destWrapper.AcquireConnections(null);
destWrapper.ReinitializeMetaData();
destWrapper.ReleaseConnections();
// source component
dtspw.IDTSComponentMetaData100 srcComponent = dataFlowTask.ComponentMetaDataCollection.New();
srcComponent.ComponentClassID = "DTSAdapter.OLEDBSource.3";
srcComponent.Instantiate();
dtspw.CManagedComponentWrapper srcWrapper = srcComponent.Instantiate();
srcWrapper.ProvideComponentProperties();
srcComponent.RuntimeConnectionCollection[0].ConnectionManager = dtsrt.DtsConvert.GetExtendedInterface(srcConnectionManager);
srcComponent.RuntimeConnectionCollection[0].ConnectionManagerID = srcConnectionManager.ID;
srcComponent.CustomPropertyCollection["CommandTimeout"].Value = 0; // no timeout
srcComponent.CustomPropertyCollection["AccessMode"].Value = 2; // sqlcommand
srcComponent.CustomPropertyCollection["SqlCommand"].Value = "select num from big_numbers2";
srcWrapper.AcquireConnections(null);
srcWrapper.ReinitializeMetaData();
srcWrapper.ReleaseConnections();
dtspw.IDTSPath100 path = dataFlowTask.PathCollection.New();
path.AttachPathAndPropagateNotifications(srcComponent.OutputCollection[0], destComponent.InputCollection[0]);
// Just one column mapping, as each table has just one column
dtspw.IDTSInput100 destInput = destComponent.InputCollection[0];
dtspw.IDTSVirtualInput100 vDestInput = destInput.GetVirtualInput();
destWrapper.SetUsageType(destInput.ID, vDestInput, vDestInput.VirtualInputColumnCollection[0].LineageID, dtspw.DTSUsageType.UT_READONLY);
// save it, run it
app.SaveToXml("D:\\myDtsx.dtsx", package, null);
dtsrt.DTSExecResult result = package.Execute(); // result = failure