ADO.NET Columns names - c#

I'm trying to get the column names using the code below but it returns a weird stuff... It returns a lot of "properties" (including the column name), all I want is a list of the columns names in the resultset. Am I doing something wrong ?
reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly);
DataTable schema = reader.GetSchemaTable();
DataRow myField = schema.Rows[0];
//For each property of the field...
foreach (DataColumn myProperty in schema.Columns)
{
host.WriteLine("##--> " + myProperty.ColumnName + " = " + myField[myProperty].ToString());
}
Thanks in advance people :)
Miloud B.

reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly);
DataTable schema = reader.GetSchemaTable();
//For each property of the field...
foreach (DataRow row in schema.Rows)
{
host.WriteLine("##--> " + row["ColumnName"]);
}
Note: I am writing this code without IDE. Please be kind.

Related

Get MS Access table creation script in C#?

Is is possible to get Ms Access Table script using C# ?
Although there is a tool that does this.
I was thinking if there is any automatic way to get the script of table .
Till now I am using
using (IDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo))
{
ret = reader.GetSchemaTable();
}
to get the schema of the table
Can we get creation script of access datatable in C# ?
Thank you All
You can create the script using the schema information, looping through columns getting the properties etc. Below is just adding column and datatype, but should be extended if the table is more intricate.
DataTable dt = reader.GetSchemaTable();
string query;
List<string> list = new List<string>();
foreach (DataRow columns in dt.Rows)
{
foreach (DataColumn properties in dt.Columns)
{
list.Add(properties.ColumnName + " " + properties.DataType);
}
}
query = string.Join(",", list);
Then build your string for the execute query.
Create Table [TableName] (
[append string here]
)

The name 'colType' does not exist in the current context

I am attempting to loop through a dataset's rows and columns in search for a match between the dataset's name column -- and the ColumnName from a DataReader object.
I have a new table called RECORDS which is empty at program startup. I also have a pre-populated table called ColumnPositions with a sub-set of column names found in the RECORDS table. This routine is intended to show a subset of all the available columns -- as a default display style.
My code works...except for the line of code that gets the dr["type"] value. I get the error:
The name 'colType' does not exist in the current context.
As you can clearly see, my string variables are declared outside the WHILE and FOREACH loops. The line statement colName = works just fine. But colType fails everytime. If I do a statement check in the Intermediate Window in VS2010 for ? dr["type"]" I get the result integer. But when I check ? colType, I get the above noted error message.
The intellisense for the DataRow object dr reveals an array of 6 items. Index 1 in the array maps to name. Index 2 maps to type. When I check the value of ? dr[2] in the Intermediate Window, the same result comes back integer. This is correct. But whenever this value is assigned to colType, VS2010 complains.
I'm no newbie to C# so I did a lot of testing and Googling before posting here. I'm hoping that this is a matter of me not seeing the forest through the trees.
Here's my code:
// get table information for RECORDS
SQLiteCommand tableInfo = new SQLiteCommand("PRAGMA table_info(Records)", m_cnCaseFile);
SQLiteDataAdapter adapter = new SQLiteDataAdapter(tableInfo);
DataSet ds = new DataSet();
adapter.Fill(ds);
DataTable dt = ds.Tables[0];
SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM ColumnPositions WHERE ColumnStyle_ID = " + styleID + " ORDER BY ColumnPosition_ID ASC", m_cnCaseFile);
SQLiteDataReader colReader = cmd.ExecuteReader();
string colName = "";
string colType = "";
if (dt != null && colReader.HasRows)
{
while (colReader.Read())
{
foreach(DataRow dr in dt.Rows)
{
colType = Convert.ToString(dr["type"]);
colName = dr["name"].ToString();
if (colReader["ColumnName"].ToString() == colName)
{
DataGridViewColumn dgvCol = new DataGridViewColumn();
}
}
}
}
dt.Dispose();
colReader.Close();
Instead of using "dr["name"].ToString();", it is better to use "Convert.ToString(dr["name"]);"
Try using the array position instead of the column name:
colType = Convert.ToString(dr[1]);
and
colName = dr[0].ToString();
You probably don't need this, but here is the documentation for values returned by the SQLite PRAGMA table_info() command. LINK

Using GetSchemaTable() to retrieve only column names

Is it possible to use GetSchemaTable() to retrieve only column names?
I have been trying to retrieve Column names (only) using this method, is it possible.
DataTable table = myReader.GetSchemaTable();
foreach (DataRow myField in table.Rows)
{
foreach (DataColumn myProperty in table.Columns)
{
fileconnectiongrid.Rows.Add(myProperty.ColumnName + " = "
+ myField[myProperty].ToString());
}
}
This code retrieves a lot of table data unwanted, I only need a list containing
column names!:
You need to use ExecuteReader(CommandBehavior.SchemaOnly)):
DataTable schema = null;
using (var con = new SqlConnection(connection))
{
using (var schemaCommand = new SqlCommand("SELECT * FROM table", con))
{
con.Open();
using (var reader = schemaCommand.ExecuteReader(CommandBehavior.SchemaOnly))
{
schema = reader.GetSchemaTable();
}
}
}
SchemaOnly:
The query returns column information only. When using SchemaOnly, the
.NET Framework Data Provider for SQL Server precedes the statement
being executed with SET FMTONLY ON.
The column name is in the first column of every row. I don't think that it's possible to omit the other column informations like ColumnOrdinal,ColumnSize,NumericPrecision and so on since you cannot use reader.GetString but only reader.GetSchemaTable in this case.
But your loop is incorrect if you only want the column names:
foreach (DataRow col in schema.Rows)
{
Console.WriteLine("ColumnName={0}", col.Field<String>("ColumnName"));
}
Change your code to below if all you want is to display the column names. Your original code was trying to not only display column names, but also trying to display the actual data values as well.
DataTable table = myReader.GetSchemaTable();
foreach (DataRow myField in table.Rows)
{
foreach (DataColumn myProperty in table.Columns)
{
fileconnectiongrid.Rows.Add(myProperty.ToString());
}
}
This will give you all column names, you can place them in a string[] and do with them what you like.
foreach(var columnName in DataTable.Columns)
{
Console.WriteLine(columnName);
}
//Retrieve column schema into a DataTable.
schemaTable = reader.GetSchemaTable();
int index = schemaTable.Columns.IndexOf("ColumnName");
DataColumn columnName = schemaTable.Columns[index];
//For each field in the table...
foreach (DataRow myField in schemaTable.Rows)
{
String columnNameValue = myField[columnName].ToString();
Console.WriteLine("ColumnName " + columnNameValue);
}
I use same technics to add MAX-STRING-LENGTH constraint on custom TextBox in my VB.Net program.
I use a SQL SELECT command to get 4 column's values
SELECT code_pays
,nom
,code_pays_short
,default_devise
FROM pays
ORDER BY nom
I use the result returned by an IDataReader object to fill a DataGridView.
And finally, I display each row's field in a Panel that contains 4 TextBox.
To avoid that SQL UPDATE command used to save some record's changes done in TextBox return error message due to column value too long, I have added a property in custom Textbox to inform directly user that value's size is overlapped.
Here is my Form
Here is VB.Net code used to initialize MaxStringLength properties
Private Sub PushColumnConstraints(dr As IDataReader)
Dim tb As DataTable = dr.GetSchemaTable()
Dim nColIndex As Integer = -1
For Each col As DataColumn In tb.Columns
If col.ColumnName = "ColumnSize" Then
nColIndex = col.Ordinal
Exit For
End If
Next
If nColIndex < 0 Then
oT.ThrowException("[ColumnSize] columns's index not found !")
Exit Sub
End If
txtCodePays.MaxStringLength = tb.Rows(0).Item(nColIndex)
txtPays.MaxStringLength = tb.Rows(1).Item(nColIndex)
txtShortCodePays.MaxStringLength = tb.Rows(2).Item(nColIndex)
txtDefaultDevise.MaxStringLength = tb.Rows(3).Item(nColIndex)
End Sub
In For loop, program search index of field contained in ColumnSize column's value.
MaxStringLength property is assigned using following syntax
tb.Rows(%TEXT-BOX-INDEX%).Item(nColIndex)
.Rows(%TEXT-BOX-INDEX%) is used to identify column's metadata in SQL SELECT !
.Item(nColIndex) is used to get a specific column's metadata value
Item(n) can return a String or an Integer but VB.Net do implicit conversion when necessary.
This line of code can also be written shortly
tb.Rows(%TEXT-BOX-INDEX%)(nColIndex)
tb(%TEXT-BOX-INDEX%)(nColIndex)
but it is not readable !
Caution: MaxStringLength is a custom property. It is not part of normal TextBox.
In print screen above, you can see that program indicates to user that length is too big for Code Pays (3 lettres) TextBox.
Error's message is displayed in StatusBar at bottom of Form.
This information is displayed before clicking on SAVE button that generates an SQL UPDATE command.
Code used that call PushColumnConstraints method is following
Public Sub FillPanel()
SQL =
<sql-select>
SELECT code_pays
,nom
,code_pays_short
,default_devise
FROM pays
ORDER BY nom
</sql-select>
Dim cmd As New NpgsqlCommand(SQL, cn)
Dim dr As NpgsqlDataReader
Try
dr = cmd.ExecuteReader()
Catch ex As Exception
ThrowException(ex)
End Try
Call PushColumnConstraints(dr)

Recursively access DataTable and input to InnerXml query

I have DataTable in my application. It holds DataColumns and Rows. I just want to call it recursively and input to InnerXml query. here Field names should be DataColumns values and Value should be Row value of DataTable. Bellow is my tried code. But I don't have idea to iterate DataTable and fill InnerXml.
DataTable DT = new DataTable();
for(int i=0 ; i<DT.Length ;i++){
batchElement.InnerXml =
"<Method ID='4' Cmd='New'>" + "<Field Name='" + DT.DataColumn[] + "'>" + DT.row + "</Field></Method>";
}
Please help me.
Do you want to simply enumerate a DataTable or do you actually want to recursively iterate it? I only ask because you example code does not show recursion, it shows enumeration with a couple parts that won't compile.
I'm guessing that you are attempting to serialise the datatable, in which case the following example would probably work:
StringBuilder innerXml = new StringBuilder();
int methodId = 0;
foreach(DataRow row in DT.Rows)
{
innerXml.AppendFormat("<Method ID='{0}' Cmd='New'>", methodId.ToString());
methodId += 1;
foreach(DataColumn column in DT.Columns)
{
innerXml.AppendFormat("<Field Name='{0}'>{1}</Field>", column.ColumnName, row[column.ColumnName]);
}
innerXml.AppendLine("</Method>");
}
batchElement.InnerXml = innerXml.ToString();
Apologies if the above does not compile - handtyped - should hopefully put you on the right track though.
NB: I'm not really sure, based on your example, how you intend to split the row and cell elements in Xml. I've made some assumptions on the Xml structure but hopefully it's enough for you to work from

How to loop through a generic object in SSIS Script Task

I have a generic object that is passed into a script task from a SQL Process. The object will essentially be a data table but in order to get the full result set from the sql process i have to store it in a generic object.
So If i have:
Object A = Dts.Variables[0];
How then would I go about extracting and then manipulating its values.
Baseically what i want to do is:
Object A = Dts.Variables[0];
strin x = A.Column[0].value.tostring();
But this obviously won't work.
I could not get any of the above answers to work, so listed below is the code I used to load the datatable. "User::transactionalRepDBs" is a SSIS variable of Object (System.Object) that was loaded through a "Full result set" from a execute SQL task script. The script task used is C#. This link assisted me.
using System.Data.OleDb;
DataTable dt= new DataTable();
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.Fill(dt, Dts.Variables["User::transactionalRepDBs"].Value);
String _showMe;
foreach (DataRow row in dt.Rows)
{
//insert what you want to do here
for (int i = 0, _showMe = ""; i < row.ItemArray.Length; i++ )
{
_showMe += row.ItemArray[i].ToString() + " | ";
}
MessageBox.Show("Data row #" + dt.Rows.IndexOf(row).ToString() + " value: " + _showMe);
}
There's nothing wrong with parsing a data table from an Object. I've seen Andy Leonard do it on his ETL frameworks.
You were on the correct path but you weren't seeing the whole picture. This code assigns the an object of type Variable (approximately) to A. You are then attempting to access a property that doesn't exist.
Object A = Dts.Variables[0];
Your need to grab the value of the variable. You can either do it as the assignment to A
Object A = Dts.Variables[0].Value;
Or if you needed to do something else with the actual variable, you'd keep your current code assignment of A then access the Value property.
Object A = Dts.Variables[0];
DataTable B = (DataTable) A.Value;
DataRow C = B.Row[0];
string x = C.Column[0].ToString();
The above code for datatable/datarow is approximate. The important take away is to access the goodies an SSIS variable is holding, you need to access the Value of the object.
Suggestion #1: Access variables by name, not numeric index.
Suggestion #2: Cast the result of the Value property to the type of object you're expecting.
Thus:
string myString = (string)Dts.Variables["MyString"].Value;
DataTable myTable = (DataTable)Dts.Variables["MyTable"].Value;
DataTable myOtherTable = Dts.Variables["MyOtherTable"].Value as DataTable;
awesome man,
This is working perfectly fine..
DataTable dt= new DataTable();
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.Fill(dt, Dts.Variables["User::transactionalRepDBs"].Value);
// Works Perfectly fine ....ssis , c#
DataTable dt = new DataTable();
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.Fill(dt, Dts.Variables["User::VariableObj"].Value);
foreach (DataColumn cols in dt.Columns)
{
MessageBox.Show("Colum Name = " + cols.ToString());
}
foreach (DataRow row in dt.Rows)
{
MessageBox.Show( "rows ID = " + row[0].ToString() + " rows
Name = " + row[1].ToString());
}

Categories

Resources