I'm trying to fetch lineageId of output columns in a SSIS Package. I'm traversing SSIS Package as XML Document in C# code.
No issue in traversing and fetching data from the nodes in the package, but facing issue when I'm trying to fetch LineageID.
I many forums and articles said that LineageId generated in SSIS Package is a Unique Integer value for that particular package, so I'm trying to convert LineageID to an integer value. But it seems to be a String value.
Kindly clarify my doubt. Is lineageid STRING OR INT?
If it is Int then please tell me how to find it.
foreach (var x in NodeCollection)
{
var outputCollection = x.Elements("outputColumn");
foreach (var output in outputCollection)
{
string Name = output.Attribute("name").Value;
long LineageId = Convert.ToInt64(output.Attribute("lineageId").Value);
}
}
By debugging with Breakpoint "output.Attribute("lineageId").Value" is returning following value
"Package\DFT\SRC.Outputs[OLE DB Source Output].Columns[TYPE]"
I have performed a very similar exercise and found that the lineage id values were definitely integer. This is an extract from my code:
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("DTS", "www.microsoft.com/SqlServer/Dts");
foreach (XmlNode childnode in doc.SelectNodes("//*[#lineageId != '' and #name != '']"))
{
XmlNode ExecutableNode = childnode.SelectSingleNode("ancestor::DTS:Executable[1]", nsmgr);
var taskName = ExecutableNode.SelectSingleNode("DTS:Property[#DTS:Name='ObjectName']", nsmgr).InnerText;
var targetColumnName = childnode.Attributes["name"].Value;
var lineageID = Convert.ToInt32(childnode.Attributes["lineageId"].Value);
We are using this to map column names to lineageid's so that we can interpret error messages thrown by our SSIS packages.
Hope this helps!
Related
I am developing an application that I need location data to be stored on MySQL table. In addition to point locations, I need regions (polygon) as well.
I am currently writing the polygon coordinates as follow :
oMySQLConnecion = new MySqlConnection(DatabaseConnectionString);
if (oMySQLConnecion.State == System.Data.ConnectionState.Closed || oMySQLConnecion.State == System.Data.ConnectionState.Broken)
{
oMySQLConnecion.Open();
}
if (oMySQLConnecion.State == System.Data.ConnectionState.Open)
{
string Query = #"INSERT INTO region (REGION_POLYGON) VALUES (PolygonFromText(#Parameter1))";
MySqlCommand oCommand = new MySqlCommand(Query, oMySQLConnecion);
oCommand.Parameters.AddWithValue("#Parameter1", PolygonString);
int sqlSuccess = oCommand.ExecuteNonQuery();
oMySQLConnecion.Close();
oDBStatus.Type = DBDataStatusType.SUCCESS;
oDBStatus.Message = DBMessageType.SUCCESSFULLY_DATA_UPDATED;
return oDBStatus;
}
After the execution, I see the Blob in MySQL table.
Now I want to read the data back for my testing and it does not work the way I tried below :
if (oMySQLConnecion.State == System.Data.ConnectionState.Open)
{
string Query = #"SELECT REGION_ID,REGION_NICK_NAME,GeomFromText(REGION_POLYGON) AS POLYGON FROM region WHERE REGION_USER_ID = #Parameter1";
MySqlCommand oCommand = new MySqlCommand(Query, oMySQLConnecion);
oCommand.Parameters.AddWithValue("#Parameter1", UserID);
using (var reader = oCommand.ExecuteReader())
{
while (reader.Read())
{
R_PolygonCordinates oRec = new R_PolygonCordinates();
oRec.RegionNumber = Convert.ToInt32(reader["REGION_ID"]);
oRec.RegionNickName = reader["REGION_NICK_NAME"].ToString();
oRec.PolygonCodinates = reader["POLYGON"].ToString();
polygons.Add(oRec);
}
}
int sqlSuccess = oCommand.ExecuteNonQuery();
oMySQLConnecion.Close();
return polygons;
}
It returns an empty string.
I am not sure if I am really writing the data since I can not read Blob.
Is my reading syntax incorrect?
** Note:** I am using Visual Studio 2017. The MySQL latest version with Spacial classes.
Any help is highly appreciated.
Thanks
GeomFromText() takes a WKT (the standardized "well-known text" format) value as input and returns the MySQL internal geometry type as output.
This is the inverse of what you need, which is ST_AsWKT() or ST_AsText() -- take an internal-format geometry object as input and return WKT as output.
Prior to 5.6, the function is called AsWKT() or AsText(). In 5.7 these are all synonyms for exactly the same function, but the non ST_* functions are deprecated and will be removed in the future.
https://dev.mysql.com/doc/refman/5.7/en/gis-format-conversion-functions.html#function_st-astext
I don't know for certain what the ST_ prefix means, but I assume it's "spatial type." There's some discussion in WL#8055 that may be of interest.
My goal is to create some kind of Parser to parse string formulas, similar to Excel formulas.
Formula string example (barcode example) -
"CONCAT('98', ZEROFILL([productNumber],5,'0'), ZEROFILL(EQUATION([weightKG]*1000),5,'0'))"
where
'98' - String
[productNumber] and [weightKG] - are variables that can be changed
CONCAT, ZEROFILL and EQUATION are methods which exist in class
For this formula with variables [productNumber] = '1' and [weightKG] = 0.1 result must be
'980000100100'
The question is how to split/parse whole string to parts and detect methods, variables and string values?
Another idea occurred, while i was typing - is to store whole formula in XML format.
Thank You.
You can use String.split() to get an array of substrings.
However, using your example, calling split(",") would give you the following array:
[0]=CONCAT('98'
[1]= ZEROFILL([productNumber]
[2]=5
[3]='0')
[4]= ZEROFILL(EQUATION([weightKG]*1000)
[5]=5
[6]='0'))
That doesn't seem like it will be very helpful for your project. Instead, you might think about creating a parse() function with some logic to find useful substrings:
function parse(input:String):Array {
var firstParen:int = input.indexOf("(");
var lastParen:int = input.lastIndexOf(")");
var formulaName:String = input.substring(0, firstParen);
var arguments:String = input.substring(firstParen, lastParen);
var argumentList:Array = parseArgs(arguments);
var result:Array = new Array();
result.push(formulaName);
//Recursively call parse() on the argumentList
foreach (var elem:* in argumentList) {
result.push(elem); //Could be string or array.
}
}
function parseArgs(input:String):Array {
// Look for commas that aren't enclosed inside parenthesis and
// construct an array of substrings based on that.
//A regex may be helpful here, but the implementation is left
//as an exercise for the reader.
}
I have a C# script in the ssis package as mentioned below
SqlConnection importTab = new SqlConnection(#"Server=ServerName;
Integrated Security=true;user=;pwd=;database=DBname");
I need to pass the database name (DBName) inside a variable...
May be like this
SqlConnection importTab = new SqlConnection(#"Server=ServerName;
Integrated Security=true;user=;pwd=;database="+"User::Variable" +");"
But I know I am wrong...
To use a variable in a script, first ensure that the variable has been added to
either the list contained in the ReadOnlyVariables property or the list contained in
the ReadWriteVariables property of this script task, according to whether or not your
code needs to write to the variable.
//Example of reading from a variable:
DateTime startTime = (DateTime) Dts.Variables["System::StartTime"].Value;
//Example of writing to a variable:
Dts.Variables["User::myStringVariable"].Value = "new value";
//Example of reading from a package parameter:
int batchId = (int) Dts.Variables["$Package::batchId"].Value;
//Example of reading from a project parameter:
int batchId = (int) Dts.Variables["$Project::batchId"].Value;
//Example of reading from a sensitive project parameter:
int batchId = (int) Dts.Variables["$Project::batchId"].GetSensitiveValue();
I do it like this:
When opening the script task properties you have two fields, ReadOnlyVariables and ReadWriteVariables. Write your variable name into the according field based on your needs, in your case User::Variable.
In the code you can use it like this
Dts.Variables["User::Variable"].Value.ToString()
Following code in the Script task may help you
var dbServerName = Dts.Variables["yourVariableName"].Value.ToString();
var sqlConnString = string.Format("Server=ServerName;Integrated Security=true;user=;pwd=;database={0}", dbServerName);
SqlConnection sqlConn = new SqlConnection(sqlConnString);
I'm working on a T4 file that generates .cs classes based on an entity model, and one of the things I'm trying to get to is the mapping info in the model. Specifically, for each field in the model I'm trying retrieve the database field name it is mapped to.
I've found that the mapping info is apparently stored in StorageMappingItemCollection, but am having an impossible time figuring out how to query it and retrieve the data I need. Has anyone worked with this class and can maybe provide guidance?
The code I have so far goes something like this (I've pasted everything up to the problematic line):
<#
System.Diagnostics.Debugger.Launch();
System.Diagnostics.Debugger.Break();
#>
<## template language="C#" debug="true" hostspecific="true"#>
<## include file="EF.Utility.CS.ttinclude"#>
<## output extension=".cs"#><#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);
string inputFile = #"MyModel.edmx";
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
StoreItemCollection storeItemCollection = null;
loader.TryCreateStoreItemCollection(inputFile, out storeItemCollection);
StorageMappingItemCollection storageMappingItemCollection = null;
loader.TryCreateStorageMappingItemCollection(
inputFile, ItemCollection, storeItemCollection, out storageMappingItemCollection);
var item = storageMappingItemCollection.First();
storageMappingItemCollection has methods like GetItem() and such, but I can't for the life of me get it to return data on fields that I know exist in the model.
Thx in advance!
Parsing the MSL isn't really that hard with Linq to XML
string mslManifestResourceName = GetMslName(ConfigurationManager.ConnectionStrings["Your Connection String"].ConnectionString);
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(mslManifestResourceName);
XmlReader xreader = new XmlTextReader(stream);
XDocument doc = XDocument.Load(xreader);
XNamespace xmlns = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
var items = from entitySetMap in doc.Descendants(xmlns + "EntitySetMapping")
let entityTypeMap = entitySetMap.Element(xmlns + "EntityTypeMapping")
let mappingFragment = entityTypeMap.Element(xmlns + "MappingFragment")
select new
{
EntitySet = entitySetMap.Attribute("Name").Value,
TypeName = entityTypeMap.Attribute("TypeName").Value,
TableName = mappingFragment.Attribute("StoreEntitySet").Value
};
It may be easier to parse the EDMX file as XML rather than using the StorageMappingItemCollection.
In an C# ASP.Net MVC project, I'm trying to make a List<string> from a LINQ variable.
Now this might be a pretty basic thing, but I just cannot get that to work without using the actual column names for the data in that variable. The thing is that in the interests of trying to make the program as dynamic as possible, I'm leaving it up to a stored procedure to get the data out. There can be any amount of any which way named columns depending on where the data is fetched from. All I care about is taking all of their values into a List<string>, so that I can compare user-input values with them in program.
Pointing to the columns by their names in the code means I'd have to make dozens of overloaded methods that all just basically do the same thing. Below is false non-functioning code. But it should open up the idea of what I mean.
// call for stored procedure
var courses = db.spFetchCourseInformation().ToList();
// if the data fails a check on a single row, it will not pass the check
bool passed = true;
foreach (var i in courses)
{
// each row should be cast into a list of string, which can then be validated
// on a row-by-row basis
List courseRow = new List();
courseRow = courses[i]; // yes, obviously this is wrong syntax
int matches = 0;
foreach (string k in courseRow)
{
if (validator.checkMatch(courseRow[k].ToString()))
{
matches++;
}
}
if (matches == 0)
{
passed = false;
break;
}
}
Now below is an example of how I currently have to do it because I need to use the names for the columns
for (int i = 0; i < courses.Count; i++)
{
int matches = 0;
if (validator.checkMatch(courses[i].Name))
matches++;
if (validator.checkMatch(courses[i].RandomOtherColumn))
matches++;
if (validator.checkMatch(courses[i].RandomThirdColumn))
matches++;
if (validator.checkMatch(courses[i].RandomFourthColumn))
matches++;
/* etc...
* etc...
* you get the point
* and one of these for each and every possible variation from the stored procedure, NOT good practice
* */
Thanks for help!
I'm not 100% sure what problem you are trying to solve (matching user data to a particular record in the DB?), but I'm pretty sure you're going about this in slightly the wrong fashion by putting the data in a List. I
t should be possible to get your user input in an IDictionary with the key being used for the column name, and the object as the input data field.
Then when you get the data from the SP, you can get the data back in a DataReader (a la http://msmvps.com/blogs/deborahk/archive/2009/07/09/dal-access-a-datareader-using-a-stored-procedure.aspx).
DataReaders are indexed on column name, so if you run through the keys in the input data IDictionary, you can check the DataReader to see if it has matching data.
using (SqlDataReader reader = Dac.ExecuteDataReader("CustomerRetrieveAll", null))
{
while (reader.Read())
{
foreach(var key in userInputDictionary.AllKeys)
{
var data = reader[key];
if (data != userInputDictionary[key]) continue;
}
}
}
Still not sure about the problem you are solving but, I hope this helps!
A little creative reflection should do the trick.
var courses = db.spFetchCourseInformation()
var values = courses.SelectMany(c => c.GetType().GetProperties() // gets the properties for your object
.Select(property => property.GetValue(c, null))); // gets the value of each property
List<string> stringValues = new List<string>(
values.Select(v => v == null ? string.Empty : v.ToString()) // some of those values will likely be null
.Distinct()); // remove duplicates