Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 Development Tools
 ASP.NET
 Contitional split via .net code

Author  Topic 

psg
Starting Member

3 Posts

Posted - 2009-09-02 : 06:17:27
Regards,

for several days I've been trying to generate a SSIS package with a data flow. The data flow is containing a simple conditional split to write data to two raw file destinations. Meanwhile, the package is basically generated, but unfortunately the package complains about the name of the destination files not being unique. The following code is used to generate the package (the AdventureWorks database is used as a data source).

private void CreateSplit2RAW(string Source)
{
// Create a package and add a Data Flow task.
Package p = new Package();
Executable e = p.Executables.Add("STOCK:PipelineTask");
TaskHost thMainPipe = e as TaskHost;
thMainPipe.Name = "Datenfluss Conditional Split";
MainPipe dataFlow = thMainPipe.InnerObject as MainPipe;

// Add an OLE DB connection manager to the package.
ConnectionManager adventureWorks = p.Connections.Add("OLEDB");
adventureWorks.Name = "OLEDB Connection Manager";
adventureWorks.ConnectionString = @"Provider=SQLNCLI;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdventureWorks;Data Source=(local);Auto Translate=False;";

// Create and configure an OLE DB source component.

IDTSComponentMetaData100 source = dataFlow.ComponentMetaDataCollection.New();
source.Name = "OLEDB_AdventureWorks";
source.ComponentClassID = "DTSAdapter.OleDbSource";
CManagedComponentWrapper instanceSource = source.Instantiate();
instanceSource.ProvideComponentProperties();
source.RuntimeConnectionCollection[0].ConnectionManager = DtsConvert.GetExtendedInterface(adventureWorks);
source.RuntimeConnectionCollection[0].ConnectionManagerID = adventureWorks.ID;
instanceSource.SetComponentProperty("AccessMode", 2);
instanceSource.SetComponentProperty("SqlCommand", "Select * from " + Source + ";");
instanceSource.AcquireConnections(null);
instanceSource.ReinitializeMetaData();
instanceSource.ReleaseConnections();

// Add conditional split transform

IDTSComponentMetaData100 splitComponent = dataFlow.ComponentMetaDataCollection.New();
splitComponent.ComponentClassID = "DTSTransform.ConditionalSplit";
splitComponent.Name = "Conditional Split";
splitComponent.Description = "Conditional Split Transform";

CManagedComponentWrapper splitWrapper = splitComponent.Instantiate();
splitWrapper.ProvideComponentProperties();

// Connect the source and the transform

IDTSPath100 path = dataFlow.PathCollection.New();
path.AttachPathAndPropagateNotifications(source.OutputCollection[0], splitComponent.InputCollection[0]);


// Configure the transform

// The transform will have a single output when first created. This is the default output and will handle any
// rows that aren't matched by any of the expressions on the other outputs. Here we are adding our new outputs
// before this one, so our default output will always be the last one in the collection. We can also control
// which output is the default one by setting the IsDefaultOut property to true.


IDTSOutput100 splitOutput = splitWrapper.InsertOutput(DTSInsertPlacement.IP_BEFORE, splitComponent.OutputCollection[0].ID);
splitOutput.Name = "Split Output";
splitOutput.Description = "Handles rows that have a CustomerID less than or equal to 500";
splitOutput.IsErrorOut = false;

//default output

IDTSOutput100 splitOutputDef = splitWrapper.InsertOutput(DTSInsertPlacement.IP_BEFORE, splitComponent.OutputCollection[1].ID);
splitOutputDef.Name = "Split Output Default";
splitOutputDef.Description = "Handles any non-matched output";
splitOutputDef.IsErrorOut = false;


// We need to set a column's usage type before we can use it in an expression.
// The code here will make all of the input columns available, but we could also
// restrict it to just the columns that we need in the conditional split expression(s).
IDTSInput100 splitInput = splitComponent.InputCollection[0];
IDTSInputColumnCollection100 splitInputColumns = splitInput.InputColumnCollection;
IDTSVirtualInput100 splitVirtualInput = splitInput.GetVirtualInput();
IDTSVirtualInputColumnCollection100 splitVirtualInputColumns = splitVirtualInput.VirtualInputColumnCollection;

int columnCount = splitVirtualInputColumns.Count;
for (int i = 0; i < columnCount; i++)
{
splitWrapper.SetUsageType(splitInput.ID, splitVirtualInput, splitVirtualInputColumns[i].LineageID, DTSUsageType.UT_READONLY);
}

// Note: You will get an exception if you try to set these properties on the Default Output.
splitWrapper.SetOutputProperty(splitOutput.ID, "EvaluationOrder", 0);
splitWrapper.SetOutputProperty(splitOutput.ID, "FriendlyExpression", "[ContactID] <= 500");

// Create and configure an OLE DB destination for first output.
IDTSComponentMetaData100 destination = dataFlow.ComponentMetaDataCollection.New();
destination.Name = "RawFile";
destination.ComponentClassID = "DTSAdapter.RawDestination";

// Create the design-time instance of the destination for first output.
CManagedComponentWrapper instanceDestination = destination.Instantiate();

// The ProvideComponentProperties method creates the first input.
instanceDestination.ProvideComponentProperties();
instanceDestination.SetComponentProperty("AccessMode", 0);
instanceDestination.SetComponentProperty("FileName", @"C:\SSIS\" + Source + "_split.raw");
instanceDestination.SetComponentProperty("WriteOption", 0);

// Create and configure an OLE DB destination for default output.
IDTSComponentMetaData100 destinationDef= dataFlow.ComponentMetaDataCollection.New();
destinationDef.Name = "RawFileDef";
destinationDef.ComponentClassID = "DTSAdapter.RawDestination";

// Create the design-time instance of the destination for default output.
CManagedComponentWrapper instanceDestinationDef = destinationDef.Instantiate();

// The ProvideComponentProperties method creates the default input.
instanceDestinationDef.ProvideComponentProperties();
instanceDestinationDef.SetComponentProperty("AccessMode", 0);
instanceDestinationDef.SetComponentProperty("FileName", @"C:\SSIS\" + Source + "_split_default.raw");
instanceDestinationDef.SetComponentProperty("WriteOption", 0);


// Create the path from transform to destination for first output.
IDTSPath100 path2 = dataFlow.PathCollection.New();
path2.AttachPathAndPropagateNotifications(splitComponent.OutputCollection[0], destination.InputCollection[0]);

// Create the path from transform to destination for default output.
IDTSPath100 path3 = dataFlow.PathCollection.New();
path3.AttachPathAndPropagateNotifications(splitComponent.OutputCollection[1], destinationDef.InputCollection[0]);


// Get the destination's first input and virtual input.
IDTSInput100 destiInput = destination.InputCollection[0];
IDTSVirtualInput100 destiVirInput = destiInput.GetVirtualInput();
IDTSVirtualInputColumnCollection100 destiVirInputColumns = destiVirInput.VirtualInputColumnCollection;
listBox1.Items.Clear();

// Get the destination's default input and virtual input.
IDTSInput100 destiInputDef = destinationDef.InputCollection[0];
IDTSVirtualInput100 destiVirInputDef = destiInputDef.GetVirtualInput();
IDTSVirtualInputColumnCollection100 destiVirInputColumnsDef = destiVirInputDef.VirtualInputColumnCollection;
listBox1.Items.Clear();



// Iterate through the virtual first input column collection.
foreach (IDTSVirtualInputColumn100 VirInputColumn in destiVirInputColumns)
{
if (VirInputColumn.DataType != Microsoft.SqlServer.Dts.Runtime.Wrapper.DataType.DT_NTEXT && VirInputColumn.DataType != Microsoft.SqlServer.Dts.Runtime.Wrapper.DataType.DT_IMAGE)
{
IDTSInputColumn100 inputColumn = instanceDestination.SetUsageType(destiInput.ID, destiVirInput, VirInputColumn.LineageID, DTSUsageType.UT_READONLY);
listBox1.Items.Add(VirInputColumn.Name + " (" + VirInputColumn.DataType + ")");
}
}

Microsoft.SqlServer.Dts.Runtime.Application a = new Microsoft.SqlServer.Dts.Runtime.Application();
a.SaveToXml(@"c:\SSIS\" + Source + "_split.dtsx", p, null);
}


Opening the package with Visual Studio 2008 generates the following error message (Translated from german, so this may not be accurate):

quote:
Error loading 'person.contact_split.dtsx': the package contains two objects with the double names 'Component 'Raw Data Destination' (98)' and 'Component 'Raw Data Destination' (92)'.


Any help would be appreciated.


Regards,

Jan

afrika
Master Smack Fu Yak Hacker

2706 Posts

Posted - 2009-09-02 : 07:47:42
simple rename one of the components and it should run.
Go to Top of Page

psg
Starting Member

3 Posts

Posted - 2009-09-03 : 07:03:20
Thanks for your reply.

Meanwhile, I solved the problem by myself. But this led to another incident:

In the generated package, the default output is not defined. I can attach several destinations, but the default output is not vonnected to any of the destinations. According to the documentation in Books Online, the property "IsDefaultOut" can be used for transformations to define the default path. Unfortunately, I always receive a COM exception when trying to set the property. Where has this one to be set?


TIA

Jan
Go to Top of Page
   

- Advertisement -