Retrieve Column name in C# - c#

I was looking around on SO on how to retrieve the column name and I tried out some solutions but when I use this method, for example, I recieve these column names and not my actual column namnes (ID, Status, Title etc.):
TABLE_CATALOG
TABLE_SCHEMA
TABLE_NAME
TABLE_TYPE
using (SqlConnection connection = new SqlConnection(this.ConnectionString))
{
System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
builder.ConnectionString = this.ConnectionString;
string server = builder.DataSource;
string database = builder.InitialCatalog;
connection.Open();
DataTable schema = connection.GetSchema("Tables");
Tables = new List<Table>();
foreach (DataRow row in schema.Rows)
{
/* Add Table */
Table t = new Table();
string tableName = row[2].ToString();
t.Name = tableName;
/* Add columns */
//DataTable dtCols = connection.GetSchema("Columns", new[] { "StarTrackerDB", null, "dbo.Tickets" });
t.Columns = new List<Column>();
foreach (DataColumn column in row.Table.Columns)
{
Column c = new Column();
c.Name = column.ColumnName;
t.Columns.Add(c);
}
Tables.Add(t);
}
}
EDIT:
I want to retrieve it in C# i.e. not execute an SQL query string in my code.
EDIT2
Current output:
TABLE_CATALOG
TABLE_SCHEMA
TABLE_NAME
TABLE_TYPE
Expected output:
ID
Status
Title
etc. the column names in the tables. the string tableName is set correctly.

I edited your code and was able to get the tables and columns with the code below.
public void testeStackOverflow()
{
using (SqlConnection connection = new SqlConnection(this.ConnectionString))
{
System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
builder.ConnectionString = this.ConnectionString;
string server = builder.DataSource;
string database = builder.InitialCatalog;
connection.Open();
DataTable schemaTables = connection.GetSchema("Tables");
foreach (System.Data.DataRow rowTable in schemaTables.Rows)
{
String TableName = rowTable.ItemArray[2].ToString();
string[] restrictionsColumns = new string[4];
restrictionsColumns[2] = TableName;
DataTable schemaColumns = connection.GetSchema("Columns", restrictionsColumns);
foreach (System.Data.DataRow rowColumn in schemaColumns.Rows)
{
string ColumnName = rowColumn[3].ToString();
}
}
}
}

Get schema information of all the columns in current database
DataTable allColumnsSchemaTable = connection.GetSchema("Columns");
You can specify the Catalog, Schema, Table Name, Column Name to get the specified column(s).
You can use four restrictions for Column, so you should create a 4 members array.
For the array, 0-member represents Catalog; 1-member represents Schema; 2-member represents Table Name; 3-member represents Column Name.
e.g. get columns for table MyTable:
String[] columnRestrictions = new String[4];
columnRestrictions[2] = "MyTable";
DataTable myTableSchemaTable = connection.GetSchema("Columns", columnRestrictions);
To get the data from these tables:
var columnDetails = from info in table.AsEnumerable()
select new {
TableCatalog = info["TABLE_CATALOG"],
TableSchema = info["TABLE_SCHEMA"],
TableName = info["TABLE_NAME"],
ColumnName = info["COLUMN_NAME"],
DataType = info["DATA_TYPE"]
};
Get schema information of all the IndexColumns in current database
DataTable allIndexColumnsSchemaTable = connection.GetSchema("IndexColumns");
You can specify the Catalog, Schema, Table Name, Constraint Name, Column Name to get the specified column(s).
You can use five restrictions for Column, so you should create a 5 members array.
For the array, 0-member represents Catalog; 1-member represents Schema; 2-member represents Table Name; 3-member represents Constraint Name; 4-member represents Column Name.
String[] indexColumnsRestrictions = new String[5];
indexColumnsRestrictions[2] = "Course";
indexColumnsRestrictions[4] = "CourseID";
DataTable courseIdIndexSchemaTable = connection.GetSchema("IndexColumns", indexColumnsRestrictions);
To get the data from these tables:
var columnDetails = from info in indexColumnsTable.AsEnumerable()
select new {
TableSchema = info["table_schema"],
TableName = info["table_name"],
ColumnName = info["column_name"],
ConstraintSchema = info["constraint_schema"],
ConstraintName = info["constraint_name"],
KeyType = info["KeyType"]
};

Related

FluentMigrator - add column to every table in loop

I'm trying to create code that adds column 'ExternalId' to almost every table in foreach loop with some exceptions. If table schema name equals "Scheduler" or table name starts with "users" dont add column.
First this I probably need is a list of schemas and tables.
public class AddExternalIdColumnsToManyTables : Migration
{
public override void Up()
{
// schema name example
// Scheduler.Job
// dbo.users_logins
var schemaAndTableNames = new List<string>();
foreach (var item in schemaAndTableNames)
{
if (item.StartsWith("Scheduler"))
{
continue;
}
if (item.Split('.')[1].StartsWith("users"))
{
continue;
}
Alter.Table(item.Split('.')[1]).AddColumn("ExternalId").AsInt32().Nullable();
}
If you're asking how to get table names:
MigrationBase class (Migration's parent) has ConnectionsString property. You can easily get it and write ADO.net query to get table names. Simple example:
var builder = new SqlConnectionStringBuilder(ConnectionString);
var query = "SELECT TABLE_NAME" +
"FROM INFORMATION_SCHEMA.TABLES" +
"WHERE TABLE_TYPE = 'BASE TABLE' AND " +
$"TABLE_CATALOG = '{builder.InitialCatalog}'"
using (var connection = new SqlConnection(builder.ConnectionString))
{
connection.Open();
var command = new SqlCommand(query, connection);
using (var sqlReader = command.ExecuteReader(CommandBehavior.KeyInfo))
{
var schemaTable = sqlReader.GetSchemaTable();
foreach (DataRow row in schemaTable.Rows)
{
///your table names
}
}
connection.Close();
}

SQL bulk copy with mapped columns

I am trying to bulk copy from one table to another by mapping the column names as the source and destination may not have same columns always.
Source can have 8 columns and destination can have 10 .. I need to map the columns and bulk copy.
Tried the below code..didn't work..getting Error: The given ColumnName 'moduleid' does not match up with any column in data source.
Source: existingtablecolumnsPresent has [collection time],[logtime],[moduleid],[node],[reason],[time],[timestamp],[usecaseid]
Destination: dataTable.Columns has [Node],[Time],[Reason],[Moduleid],[Usecaseid]
Please advise
public static void BatchBulkCopy(DataTable dataTable, string DestinationTbl, List<string> columnMapping,string filename)
{
var program = new Program();
// Get the DataTable
DataTable dtInsertRows = dataTable;
using (SqlBulkCopy sbc = new SqlBulkCopy(program.connectionStr.ToString()))
{
try {
sbc.DestinationTableName = DestinationTbl.ToLower();
string sourceTableQuery = "Select top 1 * from " + "[" + dataTable.TableName + "]";
DataTable dtSource = SqlHelper.ExecuteDataset(program.connectionStr.ToString(), CommandType.Text, sourceTableQuery).Tables[0];
for (int i = 0; i < dataTable.Columns.Count; i++)
{ //check if destination Column Exists in Source table
if (dtSource.Columns.Cast<DataColumn>().Select(a => "[" + a.ColumnName.ToLower() + "]").Contains(dataTable.Columns[i].ToString().ToLower()))//contain method is not case sensitive
{
List<string> existingtablecolumnsPresent = dtSource.Columns.Cast<DataColumn>().Select(a => "[" + a.ColumnName.ToLower() + "]").Distinct().OrderBy(t => t).ToList();
int sourceColumnIndex = existingtablecolumnsPresent.IndexOf(dataTable.Columns[i].ToString().ToLower());//Once column matched get its index
sbc.ColumnMappings.Add(dtSource.Columns[sourceColumnIndex].ToString(), dtSource.Columns[sourceColumnIndex].ToString());//give coluns name of source table rather then destination table so that it would avoid case sensitivity
}
}
sbc.WriteToServer(dtInsertRows);
sbc.Close();
}
catch (Exception ex)
{
Log.WriteLog("BatchBulkCopy" + " - " + filename, dataTable.TableName, ex.Message.ToString());
// To move a file or folder to a new location:
//if (File.Exists(program.sourceFile + filename))
// System.IO.File.Move(program.sourceFile + filename, program.failedfiles + filename);
}
As requested (create a DataTable with the columns you want to insert in them- leave the others out. Make sure any columns you leave out are marked in the table for NULL or have a DEFAULT VALUE constraint (I can't show you how to do that unless you show me your table);
//This first method is psuedoCode to explain how to create your datatable. You need to do it in the way that makes sense for you.
public DataTable createDataTable(){
List<string> excludedColumns = new List<string>();
excludedColumns.Add("FieldToExclude");
//...
DataTable dt = new DataTable();
foreach(string col in getColumns(myTable)){
if(!excludedColumns.Contains(name)){
DataColumn dC = new DataColumn(name,type);
DataTable.Add(dC);
}
return dt;
}
public List<string> getColumns(string tableName)
{
List<string> ret = new List<string>();
using (SqlConnection conn = getConn())
{
conn.Open();
using (SqlCommand com = conn.CreateCommand())
{
com.CommandText = "select column_Name from information_schema.COLUMNS where table_name = #tab";
com.Parameters.AddWithValue("#tab", tableName);
SqlDataReader read = com.ExecuteReader();
While(read.Read()){
ret.Add(Convert.ToString(read[0]);
}
conn.Close();
}
return ret;
}
//Now, you have a DataTable that has all the columns you want to insert. Map them yourself in code by adding to the appropriate column in your datatable.
public bool isCopyInProgess = false;//not necessary - just part of my code
public void saveDataTable(string tableName, DataTable table)
{
using (SqlConnection conn = getConn())
{
conn.Open();
using (var bulkCopy = new SqlBulkCopy(conn))//, SqlBulkCopyOptions.KeepIdentity))//un-comment if you want to use your own identity column
{
// my DataTable column names match my SQL Column names, so I simply made this loop. However if your column names don't match, just pass in which datatable name matches the SQL column name in Column Mappings
foreach (DataColumn col in table.Columns)
{
//Console.WriteLine("mapping " + col.ColumnName+" ("+does_Column_Exist(col.ColumnName,"Item").ToString()+")");
bulkCopy.ColumnMappings.Add(col.ColumnName, "["+col.ColumnName+"]");
// Console.WriteLine("ok\n");
}
bulkCopy.BulkCopyTimeout = 8000;
bulkCopy.DestinationTableName = tableName;
bulkCopy.BatchSize = 10000;
bulkCopy.EnableStreaming = true;
//bulkCopy.SqlRowsCopied += BulkCopy_SqlRowsCopied;
//bulkCopy.NotifyAfter = 10000;
isCopyInProgess = true;
bulkCopy.WriteToServer(table);
}
conn.Close();
}
}
Also, use this as your bolumn checker:
public bool does_Column_Exist(string colName,string tableName)
{
bool ret = false;
using (SqlConnection conn = getConn())
{
conn.Open();
using (SqlCommand com = conn.CreateCommand())
{
com.CommandText = "select count(*) from information_schema.COLUMNS where column_name = #col and table_name = #tab";
com.Parameters.AddWithValue("#tab", tableName);
com.Parameters.AddWithValue("#col", colName);
ret = Convert.ToInt32(com.ExecuteScalar()) == 0 ? false : true;
}
conn.Close();
}
return ret;
}
Is there a specific reason you need C# for this? It seems like the path of least resistance would be to use SQL to do the job.
INSERT INTO table2
(column_name(s))
SELECT column_name(s)
FROM table1;

Using ADO.Net, how do I get the database table name associated with a DataColumn?

Assume that I have a table t1 with a column c1. When I execute a 'select c1 from t1', I can get the metadata for the result using DataTable/DataRow/DataColumn using the code snippet below
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
SqlDataAdapter adapter;
DataSet dataset = new DataSet();
using (SqlConnection connection
= new SqlConnection(#"Persist Security Info=False;Trusted_Connection=True;"))
{
SqlCommand command = new SqlCommand(
#"SELECT c1 from t1 where 1 = 0;", connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
DataTable schemaTable = reader.GetSchemaTable();
Console.WriteLine(reader.GetName(0)); //Name of column
foreach (DataRow row in schemaTable.Rows)
{
//Console.WriteLine(row["TableName"]);
foreach (DataColumn column in schemaTable.Columns)
{
Console.WriteLine(String.Format("{0} = {1}",
column.ColumnName, row[column]));
}
}
}
}
}
}
But the value returned for BaseTableName is blank. Are there any other methods available to get the table 't1' associated with the column 'c1'?
Here is the output of the above code :
ColumnName = c1
ColumnOrdinal = 0
ColumnSize = 100
NumericPrecision = 255
NumericScale = 255
IsUnique = False
IsKey =
BaseServerName =
BaseCatalogName =
BaseColumnName = c1
BaseSchemaName =
BaseTableName =
DataType = System.String
AllowDBNull = True
ProviderType = 3
IsAliased =
IsExpression =
IsIdentity = False
IsAutoIncrement = False
IsRowVersion = False
IsHidden =
IsLong = False
IsReadOnly = False
ProviderSpecificDataType = System.Data.SqlTypes.SqlString
DataTypeName = char
XmlSchemaCollectionDatabase =
XmlSchemaCollectionOwningSchema =
XmlSchemaCollectionName =
UdtAssemblyQualifiedName =
NonVersionedProviderType = 3
IsColumnSet = False
you can get the table name using
schemaTable.TableName
Following links will provide you the information you are looking for:
https://msdn.microsoft.com/en-us/library/system.data.datatable.tablename(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.data.datarow.table(v=vs.110).aspx
Try the following to get all table/column info
Select * From INFORMATION_SCHEMA.COLUMNS
You've almost got it here:
//Console.WriteLine(row["table_name"]);
Try changing it to:
Console.WriteLine(row["TableName"]);

How to set database table values in a string?

I have a SQL Server database table EmpDetails and it contains two row values. I want to save these values into another table. but as per my code I can get only first row value. How to get all rows values from my EmpDetails table.
My sample code is:
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString);
SqlCommand cmd = new SqlCommand ("select e.MachID,e.Name,e.EmpCode,T.TypeName from EmpDetails e,EmpType t where e.EtypeID=t.EtypeID and e.Deptid='" + dddep.SelectedItem.Value + "'",conn);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
sda.Fill(ds);
string name = Convert.ToString(ds.Tables[0].Rows[0]["Name"]);
string code = Convert.ToString(ds.Tables[0].Rows[0]["EmpCode"]);
string type = Convert.ToString(ds.Tables[0].Rows[0]["TypeName"]);
You could try to use a loop because currently you are getting values from the first row when you say index [0].
Example:
//let n be the total rows
for(int i = 0; i < n; i++)
{
string name = Convert.ToString(ds.Tables[0].Rows[i]["Name"]);
string code = Convert.ToString(ds.Tables[0].Rows[i]["EmpCode"]);
string type = Convert.ToString(ds.Tables[0].Rows[i]["TypeName"]);
}
Hope it helps
What you can do is iterate the Rows in each Table using foreach. Since Tables[0].Rows return a DataRowCollection, you can directly put the rows in a loop:
var rows = ds.Tables[0].Rows;
foreach (DataRow row in rows)
{
var name = row["Name"];
var code= row["EmpCode"];
var type= row["TypeName"];
}
And you can use a collection to store the values for each column for each row, maybe like a list that uses a simple data model.
Hope that works!
if (ds !=null && ds.Tables.count > 0 ) {
foreach (row in ds.Tables["EmpDetails"].Rows)
{
var name = row["Name"];
var EmpCode= row["EmpCode"];
var TypeName= row["TypeName"];
}
}

How to get column names of table at runtime in C#?

Lets say I have a table in SQLServer named MyTable
ID FirstName LastName
1 Harry Dan
2 Maria Vicente
3 Joe Martin
Now if I have to insert any data in table, I will simply fire Insert Query like this
INSERT INTO MyTable (ID, FirstName, LastName) VALUES (4, Smith, Dan);
But what if I don't know the column names beforehand, I only know table name. Then is there a way to get the column name of table at runtime?
You can use sql-
SELECT name FROM sys.columns WHERE object_id = OBJECT_ID('TABLE_NAME')
Or you can query for SELECT TOP 0 * FROM TableName. Then, you can get the columns:
using(var reader = command.ExecuteReader())
{
reader.Read();
var table = reader.GetSchemaTable();
foreach (DataColumn column in table.Columns)
{
Console.WriteLine(column.ColumnName);
}
}
Another option using pure C# / .NET code:
First a helper method, that here returns a simple list of column names. Using a DataTable to hold table schema information, means that other information can also be retreived for each column, fx. if it is an AutoIncreament column etc.
private IEnumerable<string> GetColumnNames(string conStr, string tableName)
{
var result = new List<string>();
using (var sqlCon = new SqlConnection(conStr))
{
sqlCon.Open();
var sqlCmd = sqlCon.CreateCommand();
sqlCmd.CommandText = "select * from " + tableName + " where 1=0"; // No data wanted, only schema
sqlCmd.CommandType = CommandType.Text;
var sqlDR = sqlCmd.ExecuteReader();
var dataTable = sqlDR.GetSchemaTable();
foreach (DataRow row in dataTable.Rows) result.Add(row.Field<string>("ColumnName"));
}
return result;
}
The method can be called as:
var sortedNames = GetColumnNames("Data Source=localhost;Initial Catalog=OF2E;Integrated Security=SSPI", "Articles").OrderBy(x => x);
foreach (var columnName in sortedNames) Console.WriteLine(columnName);
Simply by this Query :
SELECT * FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.[table_name]')
OR This Query :
SELECT COLUMN_NAME
FROM information_schema.columns
WHERE TABLE_NAME = [table_name]
ORDER BY COLUMN_NAME
var ColName = "";
var model = new AttributeMappingSource().GetModel(typeof(DataClassesDataContext));
foreach (var mt in model.GetTables())
{
if (mt.TableName == "dbo.Table_Name")
{
foreach (var dm in mt.RowType.DataMembers)
{
ColName = dm.MappedName + ", ";
Response.Write(ColName);
}
}
}
This question was answered before in various threads
check:
How can I get column names from a table in SQL Server?
How can I get column names from a table in Oracle?
How do I list all the columns in a table?

Categories

Resources