I created a Windows Forms application in C# and my database in Visual Studio. I want to know how, if it's possible, to sort one of the columns in the table by clicking a button? Or how can I sort this column automatically without using a button?
I've tried to implement this sort in the code below, but it doesn't work :(
private c void button5_Click(object sender, EventArgs e)
{
SqlConnection sqlConnection = new SqlConnection("Here is my connecting string");
SqlCommand myCommand = new SqlCommand("SELECT * FROM [Information] ORDER BY (Перевозчик)", sqlConnection);
sqlConnection.Open();
myCommand.ExecuteNonQuery();
}
As found here: https://www.w3schools.com/sql/sql_orderby.asp
Sine we don't know what you want to oder we can only guess here.
But with the query you could try:
SELECT column1, column2, ...
FROM table_name
ORDER BY column1, column2, ... ASC
In your case:
"SELECT * FROM [Information] ORDER BY (Перевозчик) ASC"
Best would be to use the visual query builder where you can query against your database. When you are happy with your result you can at least be sure that the query is correct.
How you can do that is explained here:
https://www.c-sharpcorner.com/article/connect-to-a-database-from-visual-studio/
Since the sqlconnection and the sqlcommand is disposable you should consider putting it in a using tag, like in this example.
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand?view=netframework-4.8
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(
queryString, connection);
connection.Open();
using(SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
}
}
There is 2 way for sort data
1) sorting just data and fill into grid:
DataGridView datagridview1 = new DataGridView(); // for show data
DataTable dt1 = new DataTable(); // have data
DataTable dt2 = new DataTable(); // temp data table
DataRow[] dra = dt1.Select("", "ID DESC");
if (dra.Length > 0)
dt2 = dra.CopyToDataTable();
datagridview1.DataSource = dt2;
2) sort default view that is like of sort with grid column header:
DataGridView datagridview1 = new DataGridView(); // for show data
DataTable dt1 = new DataTable(); // have data
dt1.DefaultView.Sort = "ID DESC";
datagridview1.DataSource = dt1;
I found this solution here:
Sorting rows in a data table
For a listbox you could give this a shot
ArrayList q = new ArrayList();
foreach (object o in listBox4.Items)
q.Add(o);
}
q.Sort();
listBox5.Items.Clear();
foreach(object o in q){
listBox5.Items.Add(o);
}
I found this solution here:
Sorting a list of items in a list box
You need to do ExecuteDatareader then process the result coming from this call. ExecuteNonQuery cannot be used to retrieve data.
Related
I have three SQL Tables - Team (Id, Name), Player (Id, Name) and TeamPlayer (Id, TeamID, PlayerID). I also have two ListBoxes on my Form and want to filter the 2nd ListBox when an Item is selected on the 1st ListBox.
This is mostly setup but I'm having issues where the code is not liking the value being passed to it in the LstTeams_SelectedIndexChanged method at the commented lines.
private void Form1_Load(object sender, System.EventArgs e)
{
showTeams();
}
private void showTeams()
{
// Create the SQL Query, and an SqlDataAdapter using this query and sqlConnection declared earlier
string query = "select * from Team";
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(query, sqlConnection);
// Get the 'Team' Table and Fill it
DataTable teamTable = new DataTable();
sqlDataAdapter.Fill(teamTable);
// Populate the 'Team' ListBox with the 'Team' Table
lstTeams.DataSource = teamTable.DefaultView;
lstTeams.DisplayMember = "Name";
lstTeams.ValueMember = "Id";
}
private void LstTeams_SelectedIndexChanged(object sender, System.EventArgs e)
{
string TeamID = lstTeams.GetItemText(lstTeams.SelectedValue);
MessageBox.Show("TeamID: " + TeamID);
// Create the SQL Query, and an SqlDataAdapter using this query and sqlConnection declared earlier
string query = "select * from Player p inner join TeamPlayer tp on p.Id = tp.PlayerID where tp.TeamID = #TeamID";
SqlCommand sqlCommand = new SqlCommand(query, sqlConnection);
sqlCommand.Parameters.AddWithValue("#TeamID", lstTeams.SelectedValue); // this
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand); // causes the dataadapter to error
// Get the 'Team' Table and Fill it
DataTable teamTable = new DataTable();
sqlDataAdapter.Fill(teamTable);
// Populate the 'Team' ListBox with the 'Team' Table
lstPlayers.DataSource = teamTable.DefaultView;
lstPlayers.DisplayMember = "Name";
}
My Error is:
System.ArgumentException: 'No mapping exists from object type System.Data.DataRowView to a known managed provider native type.'
I've looked up some solutions but have been unable to get a working result.
Thank you for any help provided :).
After further research and some direction from comments made to my question, I have found success with the following:
DataRowView data = lstTeams.SelectedItem as DataRowView;
int TeamID = int.Parse(data["Id"].ToString());
string query = "select * from Player p inner join TeamPlayer tp on p.Id = tp.PlayerID where tp.TeamID = " + TeamID;
Inside the ListBox1.SelectedIndexChanged method.
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());
}
}
I have a datagridview on C# form which has large number of rows. And selection option with check boxes.
If I select 10 rows using check box selection I need to pass a column select row value to a SQL query to filter the records from another table.
Below is my coding but its not working i don't how to solve this problem.
private void button1_Click(object sender, EventArgs e)
{
SqlConnection conn1 = new SqlConnection(#"Data Source=.\sqlexpress;Initial Catalog=acc;Integrated Security=True");
SqlCommand cmd1 = new SqlCommand(#"select db.date,db.type,db.refno,db.itmcod,db.qty,db.cuscod, db.cstcod,cus.cusnam INTO ##wec from fstktxn as db INNER JOIN fcustomer as cus on db.cuscod = cus.cuscod where itmcod = "dataGridView1.Rows[j].Cells["title"].Value", ", conn1);
conn1.Open();
cmd1.ExecuteNonQuery();
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn1);
bulkCopy.DestinationTableName = "##tmp1";
conn1.Close();
}
Is there any solution to filter the data using gridview selection?
If i understand you are requirements you should be doing something like this.
First get you datagridveiw data.
DataTable data=datfridviewname.DataSource as DataTable;
con.Open();
SqlBulkCopy sbc = new SqlBulkCopy(con);
sbc.DestinationTableName = #"tableName";
sbc.WriteToServer(data);
Try reading up on this How to use parameterised queries in SQL
It shows how to add variables into your queries safely
I think what you're asking is "how can I use the selected rows in a DataGridView to form an in query?". Assuming that is try, you should break this into two steps:
obtain (from the UI) the set of values that should be used in the in query
compose and create the in query
The first step can be done by iterating over the .Rows of the DataGridView, and checking the .Checked value of (presumably) the DataGridViewCheckBoxColumn that you have; if it is checked: add the filter value to some list. For example:
List<string> titles = new List<string>();
foreach (GridViewRow row in dataGridView1.Rows)
{
if(row.Cells["CheckBoxColumnName"].Value == true)
{
titles.Add((string)row.Cells["TitleColumnName"].Value);
}
}
The second step is more complex, unless you are using a tool like "dapper" that automates it. If you are using "dapper", you could just use:
var rows = connection.Query<YourDataType>("...some query... where someColumn in #titles",
new {titles}).AsList();
and that would be it. If not, you'll need to write the command manually, for example:
var sb = new StringBuilder("...the basic query... where someColumn in (");
int index = 0;
var cmd = new SqlCommand(connection); // see also: "using"
foreach(var title in titles) {
if(index != 0) sb.Append(",");
string name = "#title" + index++;
sb.Append(name);
cmd.Parameters.AddWithValue(name, value);
}
sb.Append(")");
cmd.CommandText = sb.ToString();
then execute the command as usual. You may need to think about the zero case, too; should that be all rows? no rows?
if you are trying to get the selected checkbox rows then by using this you can get it
protected void button1_Click(object sender, EventArgs e)
{
foreach (GridViewRow gvrow in dataGridView1.Rows)
{
CheckBox chk = (CheckBox)gvrow.FindControl("chkSelect");
if (chk != null & chk.Checked)
{
SqlConnection conn1 = new SqlConnection(#"Data Source=.\sqlexpress;Initial Catalog=acc;Integrated Security=True");
SqlCommand cmd1 = new SqlCommand(#"select db.date,db.type,db.refno,db.itmcod,db.qty,db.cuscod, db.cstcod,cus.cusnam INTO ##wec from fstktxn as db INNER JOIN fcustomer as cus on db.cuscod = cus.cuscod where itmcod = "dataGridView1.Cells["title"].Value", ", conn1);
conn1.Open();
cmd1.ExecuteNonQuery();
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn1);
bulkCopy.DestinationTableName = "##tmp1";
conn1.Close();//Do something
}
}
}
I created win forms, and I wanna insert sql commands and get data from database. If I put query directly into code sql commands, everything is ok, if I put query by textbox I have a lot of bugs like:
$exception {"Could not find stored procedure 'select * from uczniowie'."}
System.Exception {System.Data.SqlClient.SqlException }
this {MateuszLab4.connectDB} MateuszLab4.connectDB
question "\"select * from uczniowie\"" string
dataTable {} System.Data.DataTable
sqlDataReader null System.Data.SqlClient.SqlDataReader
sqlCommand {System.Data.SqlClient.SqlCommand} System.Data.SqlClient.SqlCommand
Here is my code:
private void buttonSearch_Click(object sender, EventArgs e)
{
string query = textBoxQuery.Text;
connectDB databaseWin = new connectDB("(localdb)\\v11.0", "Mat");
dataGridViewAdvanced.DataSource = databaseWin.DataDownload(query);
}
When I put into string query sql commands (for example string query = "select * from students" ) everything is working very well. If I replaced with data from textbox sth is wrong. Could you give me some tips guys?
here is my class with datadownloada:
public DataTable DataDownload(string question)
{
DataTable dataTable = new DataTable();
SqlDataReader sqlDataReader;
SqlCommand sqlCommand;
sqlCommand = new SqlCommand(question);
sqlCommand.Connection = this.DBconnection;
sqlDataReader = sqlCommand.ExecuteReader();
dataTable.Load(sqlDataReader);
return dataTable;
}
Try this code.
public DataTable DataDownload(string question)
{
using (var ada = new SqlDataAdapter(question, DBconnection))
{
// Use DataAdapter to fill DataTable
DataTable dt = new DataTable();
ada.Fill(dt);
return dt;
}
}
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.