i'm currently working on my C# "WindowForm" Project and i want to know if it's possible to link a textbox from any form to a database and update the textbox content from time to time so the users of my application would get up to dates information of what i'm willing to post in this form (textbox).
thank you,
If you want to refresh the text in real time from a datatable, you can try SqlDependency.
The following is a simple demo.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
System.Data.SqlClient.SqlConnection conn = null;
System.Data.SqlClient.SqlCommand command = null;
// Set connection string
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder
{
DataSource = #"datasource name",
// set database
InitialCatalog = #"catalog name",
// access the database using the existing windows security certificate
IntegratedSecurity = true
};
private void Form1_Load(object sender, EventArgs e)
{
conn = new System.Data.SqlClient.SqlConnection(builder.ConnectionString);
command = conn.CreateCommand();
command.CommandText = "select text from dbo.TableText where id<>20 order by id desc ";
// Start
SqlDependency.Start(builder.ConnectionString);
// Get data
GetData();
}
private void GetData()
{
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(sqlDependency_OnChange);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
System.Data.DataSet ds = new DataSet();
adapter.Fill(ds, "test");
string text = ds.Tables["test"].Rows[0]["Text"].ToString();
textBox.Text = text;
}
}
void sqlDependency_OnChange(object sender, SqlNotificationEventArgs e)
{
// Because it is a child thread, you need to update the ui with the invoke method.
if (this.InvokeRequired)
{
this.Invoke(new OnChangeEventHandler(sqlDependency_OnChange), new object[] { sender, e });
}
else
{
SqlDependency dependency = (SqlDependency)sender;
dependency.OnChange -= sqlDependency_OnChange;
// After the notification, the current dependency is invalid, you need to re-get the data and set the notification.
GetData();
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Clear resource
SqlDependency.Stop(builder.ConnectionString);
conn.Close();
conn.Dispose();
}
}
For more info about SqlDependency, you can refer to Detecting Changes with SqlDependency.
Hope this can help you.
Related
I'm fairly new to C# and coding in general. I've looked through similar questions and didn't have much luck fixing this.
I am making an app that stores Student details for attendance in tables, in a database. Currently when I run it, the details are added to the tables from textboxes. A button opens a separate form with a datagridview, but the details are not updated in this. If I rerun the application and open the second form, the datagridview has been updated. How do I get the datagridview to update based on information added to the table while the application is running?
This is the code that adds the details to the table
using (SqlConnection sc = new SqlConnection())
{
sc.ConnectionString = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\corry\Desktop\StudentAttendanceBurton\Attendance.mdf;Integrated Security=True";
sc.Open();
using (SqlCommand com = sc.CreateCommand())
{
com.CommandText =
"insert into BUS102(\n" +
" Name,\n" +
" [Student ID],\n" +
" Date)\n" +
"values(\n" +
" #prm_Name,\n" +
" #prm_Student_ID,\n" +
" #prm_Date)";
com.Parameters.Add("#prm_Name", SqlDbType.NVarChar, 50).Value = student.Name;
com.Parameters.Add("#prm_Student_ID", SqlDbType.Int).Value = student.StudentID;
com.Parameters.Add("#prm_Date", SqlDbType.SmallDateTime).Value = student.Date;
com.ExecuteNonQuery();
}
}
This is the code for the form that has the datagridview
public partial class AttendanceForm : Form
{
public AttendanceForm()
{
InitializeComponent();
}
private void bUS102BindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.bUS102BindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.attendanceDataSet);
}
private void AttendanceForm_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'attendanceDataSet.BUS102' table. You can move, or remove it, as needed.
this.bUS102TableAdapter.Fill(this.attendanceDataSet.BUS102);
}
}
public partial class Form1 : Form {
private DataSet m_ds = new DataSet();
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
using (SqlConnection conn = new SqlConnection(#"Data Source=YOURSql;Initial Catalog=YOURDB;Integrated Security=True")) {
// set command
SqlCommand cmd = new SqlCommand("SELECT * FROM YourTable", conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
conn.Open();
da.Fill(m_ds);
// bind data to dataGrid
dataGridView1.DataSource = m_ds.Tables[0];
// refresh Data
dataGridView1.Refresh();
conn.Close();
}
}
private void cmdChangeData_Click(object sender, EventArgs e) {
// add new row explicit
DataRow nr = m_ds.Tables[0].NewRow();
nr[0] = "0000";
nr[1] = "xxxx";
// add new row to DataSet (just in memory, NOT TO DB)
m_ds.Tables[0].Rows.Add(nr);
// Refresh Data
dataGridView1.Refresh();
}
}
You have to refresh datagridview
this.dataGridView1.Refresh();
I'm an IT student who's always wanted to be in code hell (nah not really I really like this path I'm taking) so I'm just a beginner at using database.
so I have this problem of mine, specifically, when I try to update the form or at least the label itself, I can't connect to the Access Database I'm trying to get data from when I press the button, I like to know if I can even update the form or it's following items without losing connection to the database
if it's possible, and a better solution if you may as well, thanks in advance!
private void Form1_Load(object sender, EventArgs e)
{
Timer timer = new Timer();
timer.Interval = (1 * 1000);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
label1.Text = "";
}
private void button1_Click(object sender, EventArgs e)
{
string select = "select Input from tbl_Dta1";
string connectionValue = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=TestDatabase.accdb";
try
{
using (OleDbConnection nConnection = new OleDbConnection(connectionValue))
{
OleDbCommand cmd = new OleDbCommand(select, nConnection);
nConnection.Open();
dr = cmd.ExecuteReader();
while (dr.Read())
{
string update = dr.GetValue(0).ToString();
label1.Text = update;
}
dr.Close();
}
}
catch(Exception ex)
{
MessageBox.Show("Failed to connect to Data source");
}
}
btw, the code I just made is actually a test code
I'm testing if the timer would interrupt the connection
and the purpose of the current content of this code is just to test if the database cell I'm getting is right or wrong
I am trying to overwrite a content in an label several times by always clicking the same button. Unfortunately, I only know how to override it once.
The problem I am facing is that the data in the label are from an SQL database and it only displays the data with ID = 1 in the label.
This is my code:
MySqlConnection conn = new MySqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString); // Connectionstring to the database
public MainWindow()
{
InitializeComponent();
}
private void btContinue_Click(object sender, RoutedEventArgs e)
{
try
{
conn.Open();
MySqlCommand cmd = new MySqlCommand("SELECT l_question from l_liescale", conn);
MySqlDataAdapter adp = new MySqlDataAdapter(cmd);
DataSet ds = new DataSet();
lbquestion.Content = cmd.ExecuteScalar(); //here I get the data into the label
}
catch (MySqlException ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
conn.Close();
}
}
}
Is there a way to display every data record from the database in one label and always overwriting it with the next record by clicking the button?
You should use ExecuteReader() instead of ExecuteScalar() to retrieve collection of data.
StringBuilder sb = new StringBuilder();
using(var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var question = reader[0].ToString();
sb.AppendFormat("Q: {0}\n", question); // use any other format if needed
}
}
lbquestion.Content = sb.ToString();
But the better way is to use ItemsControl or ListBox or other list-controls.
If you want to iterate by clicking the button you can retrieve all records to the memory and then iterate it in the event handler:
private readonly List<string> _questions;
private int currentIndex = -1;
public MainWindow()
{
InitializeComponent();
_questions = GetQuestionsByDataReader();
}
private void btContinue_Click(object sender, RoutedEventArgs e)
{
if(currentIndex < _questions.Count)
{
lbquestion.Content = _questions[++currentIndex];
}
}
I have been able to bind the data in my MS Access database to textboxes on a form. But when I update the data, no changes are made to the database. I made a simplified example to demonstrate my problem. The form contains only two textboxes (txtFirstName and txtLastName) and two buttons (Save and Refresh). Refresh just reloads the DataTable from the database. I load the record with ID 1 and try to update. The code is below. I know that the updates to the textboxes also update the DataTable. However, the Update function of the data adapter does nothing because no Update commands are generated by the OleDbCommandBuilder. Can anyone tell me what I am doing wrong?
Thanks so much!
// Global data
public DataTable CaseTable = new DataTable();
private OleDbCommand dbCmd;
private OleDbDataAdapter adapter;
private OleDbCommandBuilder builder;
private OleDbConnection dbConn = null;
public frmCustomer()
{
InitializeComponent();
CaseTable.Columns.Add("ID");
CaseTable.Columns.Add("FirstName");
CaseTable.Columns.Add("LastName");
this.txtFirstName.DataBindings.Add("Text", CaseTable, "FirstName"); //, true, DataSourceUpdateMode.OnPropertyChanged);
this.txtLastName.DataBindings.Add("Text", CaseTable, "LastName"); //, true, DataSourceUpdateMode.OnPropertyChanged);
}
private void frmCustomer_Load(object sender, EventArgs e)
{
dbConn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Customers.accdb");
dbCmd = new OleDbCommand("Select * From Customers Where ID = 1", dbConn);
adapter = new OleDbDataAdapter(dbCmd);
builder = new OleDbCommandBuilder(adapter);
RefreshForm();
}
private void RefreshForm()
{
CaseTable.Clear();
adapter.Fill(CaseTable);
if (CaseTable.Rows.Count < 1)
{
MessageBox.Show("Item Not Found", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
private void btnSave_Click(object sender, EventArgs e)
{
if (adapter.Update(CaseTable) < 1)
MessageBox.Show("No updates");
}
private void btnRefresh_Click(object sender, EventArgs e)
{
RefreshForm();
}
I don't know why this works, but here is how I fixed my problem. At the end of RefreshForm I add the line
CaseTable.Rows[0].BeginEdit();
and at the beginning of the Save event handler I add the line
CaseTable.Rows[0].EndEdit();
Now the changes are carried back to the database. I'm not sure why none of the online references I found made reference to this.
I am trying to show some data in form of report in Windows Form application. I am using ReportViewer in local mode for that purpose. When i run the report, it shows empty report, no errors at all!! Here is my code:
public partial class Form1 : Form
{
String thisConnectionString = "Data Source=AZEEM-NAWAZ;Initial Catalog=IEPL_Attendance_DB;Trusted_Connection = true;";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'DataSetProducts.ShowProductByCategory' table. You can move, or remove it, as needed.
//this.ShowProductByCategoryTableAdapter.Fill(this.DataSetProducts.ShowProductByCategory);
//this.reportViewer1.RefreshReport();
//reportViewer1.Visible = false;
SqlConnection thisConnection = new SqlConnection(thisConnectionString);
System.Data.DataSet thisDataSet = new System.Data.DataSet();
string cmdText = "USE [IEPL_Attendance_DB] EXEC [ShowProductByCategory]";
SqlCommand cmd = new SqlCommand(cmdText, thisConnection);
SqlDataAdapter data_ad = new SqlDataAdapter(cmd);
data_ad.Fill(thisDataSet);
/* Associate thisDataSet (now loaded with the stored
procedure result) with the ReportViewer datasource */
ReportDataSource datasource = new ReportDataSource("DataSetProducts_DataSet1", thisDataSet.Tables[0]);
reportViewer1.LocalReport.DataSources.Clear();
reportViewer1.LocalReport.DataSources.Add(datasource);
if (thisDataSet.Tables[0].Rows.Count == 0)
{
MessageBox.Show("Sorry, no products under this category!");
}
reportViewer1.LocalReport.Refresh();
//MessageBox.Show("Total Rows are: " + thisDataSet.Tables[0].Rows[0]["EmployeeName"].ToString());
}
private void reportViewer1_Load(object sender, EventArgs e)
{
}
}
Here are report.rdlc properties:
StoredProcedure "ShowProductByCategory" is returning data and i have verified by displaying rows count via MessageBox!!!
ReportDataSource datasource = new ReportDataSource("DataSetProducts_DataSet1", thisDataSet.Tables[0]);
In the above line remove the "DataSetProducts_" build it and try you will be able to see the data