Using GetSchemaTable() to retrieve only column names - c#

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)

Related

How to get column names and other metadata from a table or resultset

EX In "Data" table
type of column from moisture to end is Boolean
I want to get column name has data is "1" to combobox
Specifically, for each row of my result set, I need a collection of those column names which contain the value 1 so I can populate a combobox.
Sorry for my English I'm not good enough.
pic "Data" table
Using the MySQL .net connector (and any RDMS connector) when you are reading a result set from a query, you will have a DataReader object. In MySQL's case it is a MySqlDataReader.
For example (from https://dev.mysql.com/doc/connector-net/en/connector-net-tutorials-sql-command.html)
string sql = "SELECT * FROM data";
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
/* iterate once per row */
Console.WriteLine(rdr[0]+" -- "+rdr[1]); /* or whatever */
}
rdr.Close();
Once you have a valid DataReader, you can use the GetSchemaTable() method to obtain a DataTable collection of data describing the result set. This information comes from MySQL as part of the result set. For example:
MySqlDataReader rdr = cmd.ExecuteReader();
DataTable schema = rdr.GetSchemaTable();
This DataTable contains a row for each column in the result set. You can access useful information about your columns in your result set like this:
foreach (DataRow rdrColumn in schema.Rows) {
String columnName = rdrColumn[schema.Columns["ColumnName"]].ToString();
String dataType = rdrColumn[schema.Columns["DataType"]].ToString();
}
There are also items named ColumnSize, NumericPrecision, NumericScale, and so forth. Each of these is available for each column in the result set if you need them.
Edit
You can make a Dictionary holding the names of the result set's columns like this:
Dictionary<int,String> columnNames = new Dictionary<int,string>();
int index = 0;
foreach (DataRow row in schema.Rows) {
columnNames.Add(index,row[schema.Columns["ColumnName"]].ToString());
index++;
}
Thereafter, as you iterate through the rows, you can create a List of columns, by name, with a certain row value.
while (rdr.Read()) {
/* for each row */
List<String> listOfColumns = new List<string>();
for (int i = 0; i < rdr.FieldCount; i++) {
var val = rdr[i];
if ("1" == val) {
/* if the value of the column is 1, add the column name from the dictionary */
listOfColumns.Add(columnNames[i]);
}
}
}
For examples of looking at result set metadata see here. https://etutorials.org/Programming/ado+net/Part+I+ADO.NET+Tutorial/Chapter+5.+DataReaders/5.4+DataReaders+and+Schema+Information/
this query will help you DESCRIBE my_table;
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'my_database' AND TABLE_NAME = 'my_table';
refer the clink for more clarification: https://dev.mysql.com/doc/refman/8.0/en/show-columns.html

How to make column names the first row?

I have a query using dynamic pivot, so the column names change based on the data. My code generates a .csv file based on the result of the query. I don't know how I can make the header, as I cannot hard-code column names. Is it possible somehow to make the header of the query result the first row of the recordset?
Thanks.
ADDED: Just realized that I don't even know how to fetch the data in my C# code if I don't know what columns I have... So that I cannot do something like this:
result.AddRange(from DataRow dr in dt.Rows
select new DailyTransactionSheet
{
Serve = Convert.ToInt32(dr["Serve"]),
Remits = Convert.ToInt32(dr["Remits"]),
List = Convert.ToInt32(dr["List"]),
Billing = Convert.ToInt32(dr["Billing"]),
DollarSent = Convert.ToInt32(dr["DollarSent"]),
FileAck = Convert.ToInt32(dr["FileAck"]),
});
}
as per comments:
basically you need to execute query and fetch information about columns form it, depending on how your're executing it, there can be several options:
SQLDataReader to fetch results, you can get column information from GetSchemaTable.Columns GetSchemaTable
or
SqlDataAdapter.Fill(DataSet) DataSet.Tables[0].Columns - these methods and properties you should read about DataSet.Tables
here is example from msdn:
private void PrintRows(DataSet dataSet)
{
// For each table in the DataSet, print the row values.
foreach(DataTable table in dataSet.Tables)
{
foreach(DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
{
Console.WriteLine(row[column]);
}
}
}
}

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

Bind or Pull a DataTable record to a MessageBox Text in C#

I am trying to make a messagebox text provide datatable results. Below is a snippet of code that I have written so far:
String mystring = comboBox1.Text;
if (mystring.Substring(0, 12) == ("Company Name"))
{
textBox2.Text = mystring.Substring(13);
ADOCon.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Name\Desktop\SmallBizDb.mdb";
ADOCon.Open();
OleDbCommandBuilder CBuilder = new OleDbCommandBuilder(DAdapter);
DAdapter = new OleDbDataAdapter("Select Companies.Company_Name From Companies Where Companies.Company_Name = '" + textBox2.Text + "'", ADOCon);
DAdapter.Fill(DTable);
MessageBox.Show(DTable.ToString());
ADOCon.Close();
ADOCon.Dispose();
}
else
Basically, if an end user types "Company Name-Company One", for example, I would like a message box to appear stating the datatable (DTable) information, which comes from a sql query. Currently, I have "messagebox.Show(DTable.ToString());", which does not work. Also, all other examples I have seen use Row indexes, such as ".Rows[0]", which I cannot use since row numbers are not involved, but rather column names and record names from the sql "where" statement within the data adapter.
There is a lot fluff here, so my major issue is how to convert my datable results so that they will show up in a message box.
Thank you,
DFM
I'm not certain what you are wanting, but if you want to display the values in your datatable you should be able to get the data from it and display it in any order you want. I think you are wanting to do something like
System.Text.StringBuilder b = new System.Text.StringBuilder();
foreach (System.Data.DataRow r in dt.Rows)
{
foreach (System.Data.DataColumn c in dt.Columns)
{
b.Append(c.ColumnName.ToString() + ":" + r[c.ColumnName].ToString());
}
}
MessageBox.Show(b.ToString());
This will loop through all the rows returned, and for each row (each company in the results) add the details in the form ColumnName:ActualValue of the dataTable.
Of course I'm not certain displaying an unknown amount of data in a message box like this is a good idea, that's just a way you can do it.

Categories

Resources