I am trying to get column names for particular data table.
I tried with this code.
datagridFieldCreation.AutoGenerateColumns = false;
DataTable dt = new DataTable();
SqlDataAdapter sda = new SqlDataAdapter("select * from Add_Information ", con);
sda.Fill(dt);
datagridFieldCreation.DataSource = dt;
I am getting full data that is there in table. But I want only column names to be displayed one by one. Can any one help me out??
You can use ExecuteReader(CommandBehavior.SchemaOnly)):
DataTable schema = null;
using (var con = new SqlConnection(connection))
{
using (var schemaCommand = new SqlCommand("SELECT * FROM Add_Information", con))
{
con.Open();
using (var reader = schemaCommand.ExecuteReader(CommandBehavior.SchemaOnly))
{
schema = reader.GetSchemaTable();
}
}
}
datagridFieldCreation.DataSource = schema;
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.
foreach (DataRow col in schema.Rows)
{
Console.WriteLine("ColumnName={0}", col.Field<String>("ColumnName"));
}
Adpated from: Using GetSchemaTable() to retrieve only column names
You can use:
SELECT * FROM YOURTABLENAME WHERE 0=1
Yes for sure, it is simple query which has a conditional statement which is always returning false, so each time you execute the query no rows will be extracted and only columns you will get so you can easily put up these columns in you DataGridView.
Related
I am coding win form app, which checks on startup right of the currently logged user. I had these right saved in MS SQL server in the table. When importing data to Datatable, there is no problem. But when I want to read value, there is message "cannot find column xy".
SqlDataAdapter sdaRights = new SqlDataAdapter("SELECT * FROM rights WHERE [user]='" + System.Security.Principal.WindowsIdentity.GetCurrent().Name + "'", conn);
DataTable dtRights = new DataTable(); //this is creating a virtual table
sdaRights.Fill(dtRights);
Object cellValue = dt.Rows[0][1];
int value = Convert.ToInt32(cellValue);
MessageBox.Show(value.ToString());
I would like, that program would save the value from SQL to int.
You are assuming that you have rows being returned, would be my first guess. You should loop through your DataTable instead of simply trying to access element 0 in it.
DataTable dtRights = new DataTable();
sdaRights.Fill(dtRights);
foreach(DataRow row in dtRights.Rows) {
Object cellValue = row[1];
int value = Convert.ToInt32(cellValue);
MessageBox.Show(value.ToString());
}
using (SqlConnection con = new SqlConnection("your connection string"))
{
using (SqlCommand cmd = new SqlCommand("SELECT [column_you_want] FROM [rights] WHERE [user] = #user"))
{
cmd.Parameters.AddWithValue("#user", System.Security.Principal.WindowsIdentity.GetCurrent().Name);
con.Open();
int right = Convert.ToInt32(cmd.ExecuteScalar());
}
}
My query is giving one result only i.e. one word for one URL when it should run for every entry in dt. Here dt is DataTable and contains many rows, url_given is a String. temp is table containing the words to be matched. Can anybody please tell me what is wrong with my query?
wordcount is the name of the table. url_String, word and count are columns.
The purpose of the query is to get the URLs matched with given URL and
their words which are in the list which is temp.
foreach (DataRow row in dt.Rows)
{
// read item
url_given = row["url_String"].ToString();
String qrystring = "select url_String,word,count from wordcount where url_String='" + url_given + "' and word in (select * from temp) ";
dt1 = db.searchandorder(qrystring);
// searchandorder is a call to a function that establishes the db connections and passes the query to the data adapter.
}
Here is my searchandorder function:
public DataTable searchandorder (String sql)
{
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
DataSet ds = new DataSet();
DataTable dt = new DataTable();
da.Fill( dt);
conn.Close();
Console.Write("table coloumns" + dt.Columns.ToString());
return dt;
}
Your problem comes from the fact you loop overwriting dt1 every time. You need to merge the results not replace them, but I can't say how you would do that without seeing db.searchandorder.
Also you have a very dangerous sql injection attack. If url_given was '; drop table wordcount; -- what would be the query the program will execute on the server? You need to use parameters with your data adapter.
EDIT: So, now that you shown your code, here is how you fix it. Instead of making a new DataTable every single time you pass you make one outside of the loop and pass in the same table every time. TableAdapter does not clear out the table before it fills by default.
private YourFunction(DataTable dt)
{
DataTable dt1 = new DataTable();
foreach (DataRow row in dt.Rows)
{
// read item
url_given = row["url_String"].ToString();
String qrystring = "select url_String,word,count from wordcount where url_String='" + url_given + "' and word in (select * from temp) ";
db.searchandorder(qrystring, dt1);
// searchandorder is a call to a function that establishes the db connections and passes the query to the data adapter.
}
DoSomthingWithResults(dt1);
}
public void searchandorder (String sql, DataTable dt)
{
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
da.Fill( dt);
conn.Close();
Console.Write("table coloumns" + dt.Columns.ToString());
return dt;
}
Now, that is the bare minimum to make your program work. There are a LOT of other bad practices you are doing.
Don't reuse a connection: Your conn object should be created inside searchandorder and be inside a using statement. Don't worry about making "too many connection", .NET will use connection pooling and reuse old connections.
Use using statments: Anything that implements IDisposable should be in a using statement (unless the item is being returned)
Follow naming standards: There is a set of standards C# code follows, your class searcandhorder should be named SerchAndOrder.
Use Parameters: You are vulnerable to a SQL injection attack use parameters for your data adapters. Not only does it improve safety, it makes your program faster by allowing SQL server to cache the query execution plan.
Here is a version of your program with those fixes applied.
private YourFunction(DataTable dt)
{
DataTable dt1 = new DataTable();
foreach (DataRow row in dt.Rows)
{
// read item
url_given = row["url_String"].ToString();
var parameter = new SqlParameter("#urlGiven", SqlDbType.VarChar, url_given.Length);
parameter.Value = url_given;
String qrystring = "select url_String,word,count from wordcount where url_String=#urlGiven and word in (select * from temp) ";
db.searchandorder(qrystring, dt1, parameter);
// searchandorder is a call to a function that establishes the db connections and passes the query to the data adapter.
}
DoSomthingWithResults(dt1);
}
public void SearchAndOrder (String sql, DataTable dt, params SqlParameter[] parameters)
{
using(var conn = new SqlConnection(_connectionString))
using(var da = new SqlDataAdapter(sql, conn))
{
da.SelectCommand.Parameters.AddRange(parameters);
conn.Open();
da.Fill(dt);
}
Console.Write("table coloumns" + dt.Columns.ToString());
return dt;
}
I have a method working with dataset,
var EmpNameList = new List<string>();
var EmpDS = GetEmployeeList();
foreach (DataRow EmpDR in EmpDS.Tables[0].Rows)
{
EmpNameList.Add(EmpDR["EmpName"].ToString()); // Error on this line
}
exception Details:
Column 'EmpName' does not belong to table 'EmpDetailTbl'
at System.Data.DataRow.GetDataColumn(String columnName)
at System.Data.DataRow.get_Item(String columnName)
at System.Data.DataRowExtensions.Field[T](DataRow row, String columnName)
at times we also get the following exception for the same method
Cannot find table 0 at System.Data.DataTableCollection.get_Item(Int32 index)
All the above exception are not reproduced consistently and it is intermittent.
The GetEmployeeList definition looks as below
public DataSet GetEmployeeList()
{
var Connectionstring = "MyConnectionString";
var query = "Select EmpName, EmpId, HireDate from EmpDetail";
DataSet ds = new DataSet();
using (OleDbConnection connection = new OleDbConnection(Connectionstring))
using (OleDbCommand command = new OleDbCommand(query, connection))
using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
{
adapter.Fill(ds,"EmpDetailTbl");
return ds;
}
}
I have tried with SQL Server using the SqlConnection class also.
This seems to be wierd huh???
If you are filling other DataTables in the DataSet then "EmpDetailTbl" may not be the first one every time (0). Refer to the DataTable by name:
foreach (DataRow EmpDR in EmpDS.Tables["EmpDetailTbl"].Rows) {
http://msdn.microsoft.com/en-us/library/y4b211hz(v=vs.110).aspx
Check out the remarks - if the actual query string you're using returns no rows, no tables are added to the dataset. Also note that the strings used are case sensitive.
I'm looking at the example here:
http://msdn.microsoft.com/en-US/library/y06xa2h1(v=vs.80).aspx
string s = "primaryKeyValue";
DataRow foundRow = dataSet1.Tables["AnyTable"].Rows.Find(s);
if (foundRow != null)
{
MessageBox.Show(foundRow[1].ToString());
}
else
{
MessageBox.Show("A row with the primary key of " + s + " could not be found");
}
They don't specify where does dataSet1 come from and does this represent some database?
I'm trying to use this example in my code to find unique rows but I can't seem to implement this syntax. I'm only using connection string to open connection to SQL and I use SqlDataAdapter to perform functions...
EDIT:
SqlConnection myConnection = new SqlConnection("Data Source=server; Initial Catalog=Dashboard; Integrated Security=SSPI; Persist Security Info=false; Trusted_Connection=Yes");
SqlDataAdapter da = new SqlDataAdapter();
try
{
//Opens the connection to the specified database
myConnection.Open();
//Specifies where the Table in the database where the data will be entered and the columns used
da.InsertCommand = new SqlCommand("INSERT INTO DashboardLibAnswer(Id,Date,Time,Question,Details,Answer,Notes,EnteredBy,WhereReceived,QuestionType,AnswerMethod,TransactionDuration)"
+ "VALUES(#Id,#Date,#Time,#Question,#Details,#Answer,#Notes,#EnteredBy,#WhereReceived,#QuestionType,#AnswerMethod,#TransactionDuration)", myConnection);
//Specifies the columns and their variable type where the data will be entered
//Special note: Conversion from String > DateTime will cause exceptions that will only import some part of data and not everything
da.InsertCommand.Parameters.Add("#Id", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#Date", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Time", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Question", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Details", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Answer", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Notes", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#EnteredBy", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#WhereReceived", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#QuestionType", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#AnswerMethod", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#TransactionDuration", SqlDbType.NVarChar);
//Using the global variable counter this loop will go through each valid entry and insert it into the specifed database/table
for (int i = 0; i < counter; i++)
{
//Iterates through the collection array starting at first index and going through until the end
//and inserting each element into our SQL Table
DataSet dashboardDS = new DataSet();
da.Fill(dashboardDS, "DashboardLibAnswer");
DataTable dt = dashboardDS.Tables["DashboardLibAnswer"];
foreach (DataColumn col in dt.Columns)
{
if (col.Unique)
{
da.InsertCommand.Parameters["#Id"].Value = collection.getIdItems(i);
da.InsertCommand.Parameters["#Date"].Value = collection.getDateItems(i);
da.InsertCommand.Parameters["#Time"].Value = collection.getTimeItems(i);
da.InsertCommand.Parameters["#Question"].Value = collection.getQuestionItems(i);
da.InsertCommand.Parameters["#Details"].Value = collection.getDetailsItems(i);
da.InsertCommand.Parameters["#Answer"].Value = collection.getAnswerItems(i);
da.InsertCommand.Parameters["#Notes"].Value = collection.getNotesItems(i);
da.InsertCommand.Parameters["#EnteredBy"].Value = collection.getEnteredByItems(i);
da.InsertCommand.Parameters["#WhereReceived"].Value = collection.getWhereItems(i);
da.InsertCommand.Parameters["#QuestionType"].Value = collection.getQuestionTypeItems(i);
da.InsertCommand.Parameters["#AnswerMethod"].Value = collection.getAnswerMethodItems(i);
da.InsertCommand.Parameters["#TransactionDuration"].Value = collection.getTransactionItems(i);
da.InsertCommand.ExecuteNonQuery();
}
}
//Updates the progress bar using the i in addition to 1
_worker.ReportProgress(i + 1);
} // end for
//Once the importing is done it will show the appropriate message
MessageBox.Show("Finished Importing");
} // end try
catch (Exception exceptionError)
{
//To show exceptions thrown just uncomment bellow line
//rtbOutput.AppendText(exceptionError.ToString);
} // end catch
//Closes the SQL connection after importing is done
myConnection.Close();
}
if you populate a dataset from your data adapter, you'll be able to follow the same logic -
http://msdn.microsoft.com/en-us/library/bh8kx08z(v=vs.71).aspx
It might be worth showing what you actually have to get more specific help
EDIT
I think I'm understanding what you want - if you fill your datatable from the already populated table, just check the item doesn't already exist before adding it - i.e.
if (dt.Rows.Find(collection.getIdItems(i)) == null)
{
// add your new row
}
(just to be sure I knocked together a quick test - hopefully this helps):
// MyContacts db has a table Person with primary key (ID) - 3 rows - IDs 4,5,6
SqlConnection myConnection = new SqlConnection("Data Source=.; Initial Catalog=MyContacts; Integrated Security=SSPI; Persist Security Info=false; Trusted_Connection=Yes");
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand("select * from Person", myConnection);
myConnection.Open();
DataSet dashboardDS = new DataSet();
da.Fill(dashboardDS, "Person");
dashboardDS.Tables[0].PrimaryKey = new[] { dashboardDS.Tables[0].Columns["ID"]};
List<int> ids = new List<int> {4, 6, 7};
foreach (var id in ids)
{
if (dashboardDS.Tables[0].Rows.Find(id) == null)
{
Console.WriteLine("id not in database {0}", id); //i.e. 7
}
}
You will first need to open a connection to your database. This is an excellent source for connection strings: The Connection String Reference.
Then you will need to fill the dataset with data from some table. Since we are only interested in the schema information we are only selecting one row (SELECT TOP 1 ...).
Then we can go through the columns and check their Unique property (Boolean):
string connString =
"server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI";
string sql = #"SELECT TOP 1 * FROM AnyTable";
using (SqlConnection conn = new SqlConnection(connString)) {
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
using (DataSet ds = new DataSet()) {
da.Fill(ds, "AnyTable");
DataTable dt = ds.Tables["AnyTable"];
foreach (DataColumn col in dt.Columns) {
if (col.Unique) {
Console.WriteLine("Column {0} is unique.", col.ColumnName);
}
}
}
}
UPDATE #1
Sorry, I missunderstood your question. The above example returns unique columns, not unique rows. You can get unique (distinct) rows by using the DISTINCT keyword in SQL:
SELECT DISTINCT field1, field2, field3 FROM AnyTable
You can then fill the data table the same way as above.
Usually the word "unique" is used for unique constraints and unique indexes in database jargon. The term "distinct" is used for rows which are different.
UPDATE #2
Your updated question seems to suggest that you don't want find unique rows, but that you want to insert unique rows (which is the exact opposite).
Usually you would select distinct items from a collection like this. However it is difficult to answer your question accurately, since we don't know the type of your collection.
foreach (var item in collection.Distinct()) {
}
UPDATE #3
The easiest way to insert distinct values in the SQL Server table is to filter the rows at their origin, when reading them from the CSV-File; even before splitting them.
string[] lines = File.ReadAllLines(#"C:\Data\MyData.csv");
string[][] splittedLines = lines
.Distinct()
.Select(s => s.Split(','))
.ToArray();
Now you have distinct (unique) splitted lines that you can insert into the SQL Server table.
i want to extract my table names and save it into variables this is my cod that return 3 answer:student, teacher and score. how can i change it to save these tree table name to 3 variable. thank you.
try
{
SqlDataReader myreader = null;
SqlCommand mycommand = new SqlCommand("select * FROM information_schema.tables WHERE table_type = 'BASE TABLE'", myconnect);
myreader = mycommand.ExecuteReader();
while (myreader.Read())
{
Console.WriteLine(myreader[2].ToString());
}
}
A simple builtin way is using Connection.GetSchema:
using (var con = new System.Data.SqlClient.SqlConnection(conStr))
{
con.Open();
DataTable schemaTable = con.GetSchema("Tables");
IList<string> allTableNames = schemaTable.AsEnumerable()
.Where(r => r.Field<string>("TABLE_TYPE") == "BASE TABLE")
.Select(r => r.Field<string>("TABLE_NAME"))
.ToList();
}
Now you have a List<string> with all table names which you can access via indexer or in a loop or create a comma separated list with string.Join:
string tNames = string.Join(",", allTableNames);
Console.Write("all tables in the given database: " + tNames);
You can use this :
string tableName ="" ; // Variable to stroe the table names
string connectionString = ""; //Your connectionstring
// get records from the table
string commandString =""; //Your query
// create the data set command object
// and the DataSet
SqlDataAdapter DataAdapter =new SqlDataAdapter(commandString, connectionString);
DataSet DataSet = new DataSet( );
// fill the DataSet object
DataAdapter.Fill(DataSet, "Customers");
// Get the one table from the DataSet
DataTable dataTable = DataSet.Tables[0];
// for each row in the table, display the info
foreach (DataRow dataRow in dataTable.Rows)
{
tableName = dataRow[0].tostring();
//...
}
if you want to save the result for future user or a different session then you can use any of the following to methods
first one
use the "insert" query to save the result one by one in the a different table that you would create specially for saving the data
you can put the insert command/statement directly into the for loop
second method
use the xml to store the value very simple and memory friendly
I Have modified #Doctor code to use ArrayList to store number of table name in single variables.
ArrayList alTableName = new ArrayList(); // Variable to stroe the table names
string connectionString = ""; //Your connectionstring
// get records from the table
string commandString =""; //Your query
// create the data set command object
// and the DataSet
SqlDataAdapter DataAdapter =new SqlDataAdapter(commandString, connectionString);
DataSet DataSet = new DataSet( );
// fill the DataSet object
DataAdapter.Fill(DataSet, "Customers");
// Get the one table from the DataSet
DataTable dataTable = DataSet.Tables[0];
// for each row in the table, display the info
foreach (DataRow dataRow in dataTable.Rows)
{
alTableName.Add(dataRow[0].tostring());
//...
}