MSDN [https://social.msdn.microsoft.com/Forums/en-US/6cd447d8-21e5-44be-aee6-ad6bdcaac40f/programmatically-created-package-having-difficulties-running?forum=sqlintegrationservices]]에 동일한 질문을 게시했으며 여기에있는 사람이 도움을 얻을 수 있기를 바랍니다.SSIS 프로그래밍 패키지 유효성 확인/실행
--- 여기에 질문 ---
내가 오라클 테이블 ([NUM]라는 하나 개의 INT 컬럼) SQL Server 테이블에서 데이터를로드하는 간단한 SSIS 작업을 만들기 위해 노력하고는 (와의 SSIS 용 .NET Interop 어셈블리를 통해 [ID]라는 하나의 NUMBER 열). 패키지를 만들고 DTSX 파일에 저장할 수 있지만 프로그래밍 방식으로 또는 dtexec을 통해 실행하면 실패합니다. 프로그래밍 방식으로 패키지를 만드는 데 대한 dev 가이드를 따르고 있습니다. 다양한 오브젝트의 속성을 살펴보면 나에게 아무 것도 나타나지 않습니다.
2 차적인 문제로, 사용 가능한 Package.Validate 메서드가있는 것을 볼 수 있지만이를 호출하는 방법을 알지 못합니다 (인수와 반환 값이 필요합니다). dtexec을 통해 패키지를 실행할 때 유효성 검사를 수행하고 다소 유용한 유효성 검사 오류를 제공하므로 프로그래밍 방식으로 연결할 수 있기를 바랍니다.
내가 얻는 유효성 검사 오류는 다음과 같습니다
나는 온라인으로 무엇을 말할 수에서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".
,이 오류의 원인은 나쁜 열 매핑이다, 그러나 나는 dev에 가이드에서 더 많거나 적은 바로 코드를 해제했습니다 .
그래서 내 두 가지 질문은 다음과 같습니다
- 어떻게이 유효성 검사 오류 VS_NEEDSNEWMETADATA, 바람직하게는 프로그래밍 방식으로 문제를 해결할 수 있습니다?
- 어떻게 프로그래밍 방식으로 이러한 유효성 검사 오류를 얻기 위해 Package.Validate를 호출 할 수 있습니다? **
어떤 도움에 감사드립니다!
목록 전체 코드 (I 비주얼 스튜디오를 사용하여 C# 대화에서 이것을 실행, 예외가 발생되지하지만 결과는 실패의 값으로 끝나는된다) :
// 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
코드의 첫 번째 줄에서 destInput.InputColumnCollection을 의미한다고 가정합니다. 그게 분명히 효과가 있었기 때문에! 이 답변을 표시하고 있지만, 내가 배운 방식을 확장 할 수 있다면 감사히 여길 것입니다. 나는 MSDN의 문서를 읽었으며, 그들은 희소하고 파악하기 힘들거나 밀도가 높다. 정말 알고 싶다. –
예. 코드의 첫 번째 줄에는 destInput이 사용됩니다. –
학습만큼, 대부분 문서화를 통해 코딩하고 dtsx의 XML에서 변경 사항을 관찰하는 것이 었습니다. 조만간 모든 파이프 라인 구성 요소 (조회 또는 병합 또는 소스 등)가 구성되는 것과 동일한 설계 원칙을 따름을 알게 될 것입니다. 이것에 몇 가지 메모를 합쳐서 알려 드리겠습니다. 한편, 다른 프로그래밍 방식의 질문이 있으면 알려주십시오. –