I'm hitting a wall right now in my project.
I have a form, with some listboxes, and add button. When I click on the add button, I got a small dialog form with a textbox, an OK and a Cancel button. The app is connected to a MySQL database. So whenever the text change, the program checks if the name exists in the database, disable the OK button and the textbox turn red if the name exists, otherwise it turns them back to normal. Works without a problem when I'm writing and the name doesn't exist, and when it does, it turns red, like it should. And here is the problem. After turning red, it doesn't go back to normal, even when I enter a valid name.
Here is the code :
private void DialogTxb_TextChanged(object sender, EventArgs e)
{
//ConnexionData class where i do all the SQL manipulation
MySqlDataReader selection = ConexionData.CheckSectionName(DialogTxb.Text);
while (selection.Read())
{
if (selection.HasRows)
{
DialogOk.Enabled = false;
toolTip1.Show("La section existe", TooltibLb);
DialogTxb.BackColor = System.Drawing.ColorTranslator.FromHtml("#ffaaaa");
}
else
{
toolTip1.Hide(TooltibLb);
DialogTxb.BackColor = Color.White;
DialogOk.Enabled = true;
}
}
ConexionData.ConexionClose();//Method to close connection
}
I think I have an idea where the problem is but have don't know why it happens and how to solve it. If I simply exit the form and try to do anything else, like select another element from a listbox which will trigger some database interaction, the program close and visual studio provide me with info on the error:"The connexion is already open". I tried to close in other moments of the code, looked for some solutions on the internet, tried MysqlConection.ClearAllPools(), and still the same issue.
Connexion opens and closes properly in other parts of the application.
Thanks for your attention.
Edit
Here are the methods in ConexionData
class ConnexionData
{
private static MySqlConnection Connexion;
public static MySqlCommand Command;
//Many other methods
//.......
public static void ConnexionClose()
{
Connexion.Close();
}
public static MySqlDataReader CheckSectionName(string name)
{
Connexion.Open();
string checkSectionName = ("Select sectionName from section where sectionName = '" + name + "'");
Command.CommandText = checkSectionName;
Reader = Command.ExecuteReader();
return Reader;
}
}
I use the Connexion.Close() in many parts of the program. I have 2 Data Grid views, and some list box where i load data from the database. I open and close those DGV and change values in listbox and all work fine. Then i try my small form to insert a new values on those tables, test it and close it (actually i insert nothing, i simply close it and there is a ConexionData.Close() in the close event) and here where the problem of connection start.
Edit-Solved
I finally solved the problem. I turned Private MysqlConection to public, and directly closed the property after closing the dialog.
if selection.Read() returns true it means you have at least 1 record. It seems you are looking for
private void DialogTxb_TextChanged(object sender, EventArgs e) {
try {
//TODO: check ConexionData.CheckSectionName (re-)creates connection if required
using (MySqlDataReader selection = ConexionData.CheckSectionName(DialogTxb.Text)) {
if (selection.Read()) {
// Name exists (we've read it)
DialogOk.Enabled = false;
toolTip1.Show("La section existe", TooltibLb);
DialogTxb.BackColor = System.Drawing.ColorTranslator.FromHtml("#ffaaaa");
}
else {
// Name doesn't exist: the cursor is empty (so we've failed to read it)
toolTip1.Hide(TooltibLb);
DialogTxb.BackColor = Color.White;
DialogOk.Enabled = true;
}
}
}
finally {
// finally: rain or shine the connection should be closed
ConexionData.ConexionClose(); // Method to close connection
}
}
In case connection is not closing then you can try to call close() connection or sqldatareader before executing method "CheckSectionName()".
FYR Below is some example Let me know, if it helps.
Approch 1:
System.Data.SqlClient.SqlConnection sqlConn = new System.Data.SqlClient.SqlConnection();
if(sqlConn.State!= System.Data.ConnectionState.Closed)
{
sqlConn.Close();
}
System.Data.SqlClient.SqlDataReader SqlReader= new System.Data.SqlClient.SqlDataReader();
if(!SqlReader.IsClosed)
{
SqlReader.Close();
}
MySqlDataReader selection = ConexionData.CheckSectionName(DialogTxb.Text);
Approch 2: We can use "using" clause
using (MySqlDataReader selection = ConexionData.CheckSectionName(DialogTxb.Text))
Approch 3:
Add close() and dispose() into finally block.
Related
private void btnPublish_Click(object sender, EventArgs e)
{
Sqlbaglan.NesneVer().thisConn = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb;initial catalog = ManagerPanel;integrated security = true");
Sqlbaglan.NesneVer().thisConn.Open();
Sqlbaglan.NesneVer().thisQuery = new SqlCommand("SELECT Kurallar FROM [Rules] WHERE TC=#TC", Sqlbaglan.NesneVer().thisConn);
Sqlbaglan.NesneVer().thisQuery.Parameters.AddWithValue("#TC", tbxTC.Text);
label1.Text = Sqlbaglan.NesneVer().thisQuery.ExecuteScalar().ToString();
Sqlbaglan.NesneVer().thisConn.Close();
}
Friends, I have 2 problems, I do not have much knowledge of SQL, but I wanted to do my job with the database. I created a SQL connection and query object with singleton dp. I called the rule that has that TC with the TC entered in tbxTC and printed it on label1.Text in the SAME FORM. So far, everything happens as I want. My 1st problem is that when I open and close the form, label1.Text gets reset. Consider my second problem independent of my first problem. My second problem is that I have written in capital letters already - I am nervous- I have to show it in another form. This form's name is frm2. So consider label1.text is in another form.
I am creating a form with several calculations from the same table (in this case). The code works fine, but I could with with some guidance to make sure I am doing things efficiently:
When the form loads, I simply want two textblocks to be populated with counts. I know that I will need to put some error checking in, but outside of that - is this a good way of doing it?
private void Window_Loaded(object sender, RoutedEventArgs e)
{
int intCount = ReturnNumber("SELECT COUNT(ActivityID) FROM tblActivity WHERE [Activity_Category] = 'Productivity'");
TxtBlockProductivityPerc.Text = intCount.ToString();
intCount = ReturnNumber("SELECT COUNT(ActivityID) FROM tblActivity WHERE [Activity_Category] = 'Revenue'");
TxtBlockRevenuePerc.Text = intCount.ToString();
}
public int ReturnNumber(string StrQuery)
{
string cs = ClsVariables.StrDb;
string cmdText = StrQuery;
using (SQLiteConnection con = new SQLiteConnection(cs))
using (SQLiteCommand cmd = new SQLiteCommand(cmdText, con))
{
con.Open();
int count = Convert.ToInt32(cmd.ExecuteScalar());
con.close();
return count;
}
}
Basically, if you are not developing an application in MVVM style, such an approach is not bad, but it's just my opinion. Here a couple of my comments:
In this situation, I think better to use event Window.ContentRendered, because Loaded event is triggered when loading Window as Control, and the ContentRendered event triggered when rendering the contents of the Window. But the big difference no between them link.
You have to be separately stored query strings, because every time we need to change them, you'll have to climb into your function, which is not convenient.
Add to the functions that work with SQL server prefix FromSQL, in your case will be something like this: ReturnNumberFromSQL().
You do not need a temporary variable, you can call the function and immediately get a result from it.
My pseudo example:
private void Window_ContentRendered(object sender, EventArgs e)
{
string Test1Sql = "Test1 SQL query"; // stored separately
string Test2Sql = "Test2 SQL query"; // stored separately
MyTextBlock1.Text = ReturnNumberFromSQL(Test1Sql).ToString();
MyTextBlock2.Text = ReturnNumberFromSQL(Test2Sql).ToString();
}
public int ReturnNumberFromSQL(string StrQuery)
{
return 777;
}
And think on the expense of having to store procedures that do not work with GUI separately in the appropriate class.
Im trying to create UPDATE command to my program based on C# and Access database. And its working how i want it, but VS2013 display error when i try to update another or the same record second time.
InvalidComObjectException was unhandled.
COM object that has been separated from its underlying RCW can not be
used.
This is how my program looks like:
FormA - Main windows with DataGridView1 of table "Grafik" and Button to open FormB
FormB - Second form with DataGridView2 of table Employyes and Button to FormC
FormC - Form to add, delete and update records directly in to the database "Kategorie" using TextBox'es, ComboBox'es and Buttons (no directly on DataGridView)
UPDATE procedure uses ComboBox (comboBoxWybierzKategorie) to select "category" from database "Kategorie" to update, textBox (textBoxEdytujKategorie) to set new name of selected "Kategoria" and Button to accept procedure.
Broker.cs
public void Update_Kategorie(Kategorie oldKategoria, Kategorie newKategoria)
{
try
{
command.CommandText = "UPDATE Kategorie SET Kategoria = #kat WHERE IDKategorii= #old";
//command.CommandType = CommandType.Text;
command.Parameters.AddWithValue("#kat", newKategoria.Kategoria);
command.Parameters.AddWithValue("#old", oldKategoria.IDKategorii);
connection.Open();
//command.ExecuteNonQuery();
int cmd = command.ExecuteNonQuery();
//connection.Close();
if (cmd > 0)
{
MessageBox.Show("Kategoria zaktualizowana pomyślnie");
//connection.Close();
}
else
{
MessageBox.Show("Wystąpił błąd podczas aktualizacji kategorii.",
"Dodawanie kategorii",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button1);
}
}
catch (OleDbException ex)
{
FormC.cs
private void buttonEdytujKategorie_Click(object sender, EventArgs e)
{
Kategorie oldKategoria = new Kategorie();
Kategorie newKategoria = new Kategorie();
oldKategoria = comboBoxWybierzKategorie.SelectedItem as Kategorie;
newKategoria.Kategoria = Convert.ToString(textBoxEdytujKategorie.Text);
b.Update_Kategorie(oldKategoria, newKategoria);
comboBoxWybierzKategorie.DataSource = b.FillComboBox_Kategorie(); //wypełnij comboBoxWybierzKategorie
textBoxEdytujKategorie.Text = String.Empty; //wyczyść textBoxEdytujKategorie
//this.Close();
//this.Controls.Clear();
//this.InitializeComponent();
I know that code is messed up, sorry for that. More interesting is when i close FormC and reopen it using Button, update function working fine, unless i want use it again.
VS2013 selecting this line as a reason of error:
int cmd = command.ExecuteNonQuery();
Connection to database:
OleDbConnection connection;
OleDbCommand command;
private void ConnectTo()
{
//inside//connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=bc3e-ps.accdb");
/*outside*/
connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\bc3e-ps.accdb");
command = connection.CreateCommand();
What im doing wrong?
Since you are adding parameters to the command every time, you should not re-use the command object again.
Just call connection.CreateCommand() every time you want to execute another command.
You can re-use commands, but then you only want to set the existing parameters on each call instead of adding parameters on each call.
I'm trying to make a DataGridView that displays data from an SQL database (GSM.sdf) and saves changes made to the DataGridView back to the database when a save button is pressed. The data displays fine, but nothing happens when the save button is pressed. I've been following the top answer from this thread:
http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/98bc0b4d-a2ea-4b74-81f0-473da624528a
But it isn't working out. Here is my code:
namespace WindowsFormsApplication5
{
public partial class Zeelot : Form
{
DataTable table = new DataTable();
SqlCeDataAdapter z;
DataSet gSMDataSet = new DataSet();
public Zeelot()
{
InitializeComponent();
}
private void Zeelot_Load(object sender, EventArgs e)
{
string b = #"Data Source =.\SQLEXPRESS;database=GSM;Integrated Security=FALSE;Connection Timeout=30;User Instance=FALSE";
SqlCeConnection conn = new SqlCeConnection(b);
conn.Open();
string cd = "SELECT * FROM PhoneNumbers";
z = new SqlCeDataAdapter(cd, conn);
z.Fill(gSMDataSet, "PhoneNumbers");
table = gSMDataSet.Tables[0];
conn.Close();
dataGridView1.DataSource = table;
}
private void SaveButton_Click(object sender, EventArgs e)
{
SqlCeCommandBuilder local_SqlCommandBuilder = new SqlCeCommandBuilder(z);
local_SqlCommandBuilder.ConflictOption = System.Data.ConflictOption.OverwriteChanges;
z.UpdateCommand = local_SqlCommandBuilder.GetUpdateCommand();
z.Update(((System.Data.DataTable)this.dataGridView1.DataSource));
((System.Data.DataTable)this.dataGridView1.DataSource).AcceptChanges();
}
}
}
I believe your problem lies where you are casting a DataSource to System.Data.DataTable
Try z.Update(gSMDataSet);
I also don't believe you need AcceptChanges()
you dont need to call .AcceptChanges() on the DataGridView at the end.
AcceptChanges() submits the changes from your DGV to the connected DataSource (your DataTable)
Try calling AcceptChanges() before you try to submit the changes to your Database.
I think your problem is with your connection. You manually create and open a connection and assign it to your DataAdapter. But within your _Load() Method, you close the connection. As the DataAdapter used inside the _Click EventHandler is the same as the one used in your _Load() Method (therefore uses the same connection). It can't submit any changes to your Database because you already closed the connection.
Don't you get any exceptions at runtime?
Try using breakpoints to examine the current state of your connection Object before you attempt to submit your changes to your Database.
Also, AFAIK MS advises against creating connections manually if you want to use them within a DataAdapter.
DataAdapter's Constructor can create a connection on its own
I've tried setting up an SQL Dependency to fire on a "Count Rows" query (written in C#, SQL Server 2008 Express), but after the original subscription SQLNotificationType goes, the event handler never seems to want to fire again (despite rows being added, and I've checked the SQL and it's returning the expected value...).
My code is below. Any thoughts are much appreciated!
EDIT: The project that this code is in is a WPF program. I have this particular code stored in a separate class, which my WPF program creates an instance of in an 'Initialized' event handler. I then have a method in this class that basically calls ConnectToDatabase() first, and then calls SetupSQLDependency().
EDIT 2: As a side note, this program is a WPF which I was hoping to distribute to a few users. The goal was to have the WPF update with certain information whenever new rows were added to a database. I thought that this would be the best way to go about it, as opposed to always querying the database.
private void ConnectToDatabase()
{
//This method is the first to be called, and is the entry
// point into my SQL database code.
databaseConnection = new SqlConnection(connectionString);
// Setup command used in SqlDependecy
SqlCommand tempCmd = new SqlCommand();
tempCmd.Connection = databaseConnection;
tempCmd.CommandText = "SELECT COUNT(ID) FROM [Example].[dbo].[ExampleTable]";
sqlCmd = tempCmd;
try
{ databaseConnection.Open(); }
catch (Exception e)
{ writeDebug(e.ToString()); }
}
private void SetupSQLDependency()
{
SqlDependency.Stop(connectionString);
SqlDependency.Start(connectionString);
sqlCmd.Notification = null;
// create new dependency for SqlCommand
SqlDependency sqlDep = new SqlDependency(sqlCmd);
sqlDep.OnChange += new OnChangeEventHandler(sqlDep_OnChange);
SqlDataReader reader = sqlCmd.ExecuteReader();
}
private void sqlDep_OnChange(object sender, SqlNotificationEventArgs e)
{
// FROM: http://msdn.microsoft.com/en-us/a52dhwx7.aspx
if (e.Type == SqlNotificationType.Change)
{
//++++++ THIS IS THE BLOCK THAT IS NEVER TRIGGERED ++++++//
// Have to remove this as it only work's once
SqlDependency sqlDep = sender as SqlDependency;
sqlDep.OnChange -= sqlDep_OnChange;
// Resetup Dependecy
SetupSQLDependency();
}
else if (e.Type == SqlNotificationType.Subscribe)
{
double te = 12; // Used this just to test a break... code is useless
}
}
I believe the problem here is the COUNT. Refer to the MSDN documentation for Supported SELECT Statements for more info:
The projected columns in the SELECT statement may not contain aggregate expressions unless the statement uses a GROUP BY expression. When a GROUP BY expression is provided, the select list may contain the aggregate functions COUNT_BIG() or SUM(). [...]