Visual studio not loading data from Microsoft SQL Server Management Studio - c#

I am try to retrieve the data from my table which I created on my SSMS. I created a list box in a form of visual studio, and I try to display the data from database, but it doesn't send anything when I try to load up the program. The database is seems to look good. That problem appear when I try to retrieve the movie_id and movie_title.
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DataBase
{
public partial class Form1 : Form
{
DataTable dt = new DataTable();
public void LoadData()
{
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;"+
"Initial Catalog=online_tv;Integrated Security=SSPI;");
SqlCommand cmd = new SqlCommand("SELECT movie.* FROM movie", conn);
SqlDataAdapter sa = new SqlDataAdapter(cmd);
conn.Open();
sa.Fill(dt);
conn.Close();
sa.Dispose();
cmd.Dispose();
conn.Dispose();
}
public class MyMovie
{
public int id;
public string title;
public override string ToString()
{
return title;
}
}
public void ShowMovies()
{
int i;
for (i = 0; i < dt.Rows.Count; i++)
{
MyMovie movie = new MyMovie();
movie.id = Convert.ToInt32(dt.Rows[i]["movie_id"]);
movie.title = Convert.ToString(dt.Rows[i]["movie_title"]);
listBox1.Items.Add(movie);
}
}
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
LoadData();
ShowMovies();
}

There are a bucketload of optimizations to be made here, but I'd like to post an answer that introduces a small but fundamental change that will make your life significantly easier. Nearly every single line of code you've written there, you can get Visual Studio to write for you; just like you get it to write code when you lay out a Form, you can have it do all of this data access stuff too, and if you've managed to get SSMS connected, then getting VS connected is virtually the same process and will mean it just works:
Add a DataSet type of file to your project, and open it
Right click on it and choose add a TableAdapter - this is like a DataAdapter on steroids
Add a new conenction - the dialog is virtually the same as SSMS so you should be able to connect your DB without any hassle
Say you want to write "a query that returns rows" - put SELECT * FROM movie in
Finish the wizard
Right click the "Fill" line in the tableadapter and choose Preview Data, hit the button and see your data. If you see no data, you connected to a database that is devoid of data
Go to your form, open the Data Sources window (View menu.. Other Windows)
Drag the movie node out of the Data Sources window and onto the form
Run the app
You'll see your data
Now that you've scratched the surface of this, you can start playing with other stuff. Throw the DataTable dt away; you won't need it. Your form has a dataset object on it, that contains a Movie property that is a MovieDataTable - a subclass of datatable that you can access in a more logical and modern manner than via "string column names" - you say, for example, yourdatasetnamehere.Movies[0].movie_title and it's already a string (time to swap your column names to PascalCase by the way) rather than somedatatable.Rows[0]["movie_title"].ToString()
To show your movies in a listbox,
add a listbox to the form
set the DataSource property to be the movieBindingSource
Set the DisplayMember to be movie_title
(All this is done visually on the forms designer, not in code)
You can consider throwing the Movie POCO away too; a MovieDataRow is created by the dataset generator; it has all the properties of your movie, in a strongly typed fashion, just like your POCO does. The tableadapter downloads the DB data and turns it into strongly typed MovieDataRow objects for you, meaning you can throw all the POCO mapping stuff in ShowMovies away too, and finally, databinding your listbox means you can toss out the bit where you build its items collection manually.

Related

Pulling data into a grid view using 1 method and getting null ref exception when saving changes

Good day everyone,
Firstly I would like to thank anyone in advance who takes the time to look through this lengthy post.
Context: I am building a simple GUI interface using windows forms and c sharp that connects to a MySql database to perform CRUD operations.
Problem: I am trying to implement a method that would take the necessary MySql code elements as arguments and pull a table into a data grid view. I have produced 2 methods - 1 that takes arguments and the other one which is hard coded to pull the data.
After pulling the data I am able to insert/amend any records in the database with a SAVE button method. The issue is that when I use the method that takes the arguments to pull the data into the grid view I am not able to SAVE my changes as I get a null reference error. However when using the hard coded method I don't get any null errors and all works fine. For some reason when the sqlDataand dataTable variables are passed to the SAVE button method AFTER the grid view gets filled with the method based on arguments they end up as null. Any experts that have experience building these applications have any advice please?
Hard coded method for pulling data into grid view:
private void fill_grid_view1(string sequelQueryString)
{
using (MySqlConnection mysqlConn = new MySqlConnection(db_connection))
{
mysqlConn.Open();
sqlData = new MySqlDataAdapter(sequelQueryString, mysqlConn);
sqlCommandBuilder = new MySqlCommandBuilder(sqlData);
dataTable = new DataTable();
sqlData.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
The SAVE button methods:
private void bttnSave_Click(object sender, EventArgs e)
{
save_changes_refresh(sqlData, dataTable);
}
private void save_changes_refresh(MySqlDataAdapter given_data_adapter, DataTable given_data_table)
{
try
{
given_data_adapter.Update(given_data_table);
select_both_user_tweet();
MessageBox.Show("Your changes have been saved successfully!"); //
}
catch (Exception errobj)
{
MessageBox.Show(errobj.Message.ToString());
}
}
The method I want to use to pull data into grid view based on given arguments:
private void fill_given_grid_view (string sequelQueryString, MySqlDataAdapter given_data_adapter, DataTable given_data_table, DataGridView given_grid_view,
MySqlCommandBuilder given_builder)
{
using (MySqlConnection mysqlConn = new MySqlConnection(db_connection))
{
mysqlConn.Open();
given_data_adapter = new MySqlDataAdapter(sequelQueryString, mysqlConn);
given_builder = new MySqlCommandBuilder(given_data_adapter);
given_data_table = new DataTable();
given_data_adapter.Fill(given_data_table);
given_grid_view.DataSource = given_data_table;
}
}
All the new method does is pull data based on arguments so that if I had let's say 5 dataGridView elements I wouldn't need to hard code all five pull methods separately like I did in the first code snippet. And it works but it doesn't let me save any changes as mentioned above because of the sqlData and dataTable variables end up as null when I try to execute the save method.
Method that passes the needed parameters to fill_given_grid_view:
private void view_users_Click(object sender, EventArgs e)
{
fill_given_grid_view("SELECT * FROM new_schema.user", sqlData, dataTable, dataGridView1, sqlCommandBuilder);
}
EDIT: I've read the possible duplicate thread and it is useful however I struggle to understand why essentially using 2 methods that do the same thing one of them drops the sqlData and dataTable variables to null and the hard coded method from the first snippet does not drop the variables and keeps the needed values to pass into the SAVE method.
Based on #Reniuz suggestions the fill_given_grid_view and save_changes_refresh methods had to be rewritten to take in dataGridView and sequelQueryString as arguments. sqlData and dataTable variables are not used anywhere as input to a method. Code examples below:
Method to pull data into a grid view based on input:
private void fill_given_grid_view (string sequelQueryString, DataGridView given_grid_view) /* master method that takes an SQL query and grid view as input
and displays a table accordingly */
{
using (MySqlConnection mysqlConn = new MySqlConnection(db_connection)) // using stored connection params
{
mysqlConn.Open();
sqlData = new MySqlDataAdapter(sequelQueryString, mysqlConn);
sqlCommandBuilder = new MySqlCommandBuilder(sqlData);
dataTable = new DataTable(); // new dataTable created, filled based on given query and set as the DataSource of the grid given as input to the method
sqlData.Fill(dataTable);
given_grid_view.DataSource = dataTable;
}
}
SAVE method rewritten with grid view and sequel string as arguments:
private void save_changes(string sequelQueryString, DataGridView given_grid_view) /* master save method that initializes a new Data Adapter based on given sequel string
that saves any changes inputted into the given grid view */
{
using (MySqlConnection mysqlConn = new MySqlConnection(db_connection))
{
mysqlConn.Open();
sqlData = new MySqlDataAdapter(sequelQueryString, mysqlConn);
sqlCommandBuilder = new MySqlCommandBuilder(sqlData);
var current_data_table = (DataTable)given_grid_view.DataSource; // if any changes occur in given grid view db table is updated when a "SAVE" button is clicked
sqlData.Update(current_data_table);
}
}

Connecting variables to another class

So I have a small project I am working on. Basically what I want to do is create another class, with the SQL connection as well as the results. However, it is telling me:
The Name 'firstName' does not exist.
When I put it on the page that is created for the designer mode in visual studio, it goes away and works.
info.cs:
public void GetInfo(string accountNumber)
{
string source = helper.CnnVal("WorkflowConfiguration");
SqlConnection con = new SqlConnection(source);
con.Open();
string sqlSelectQuery = $"Select TOP 1 * From [Workflow Creation].[dbo].[ssFields] Where Field16 =" + int.Parse(accountNumber);
SqlCommand cmd = new SqlCommand(sqlSelectQuery, con);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
firstName.Text = (dr["Field1"].ToString());
lastName.Text = (dr["Field2"].ToString());
dateOfbirth.Text = (dr["Field3"].ToString());
socialSecurity.Text = (dr["Field4"].ToString());
}
con.Close();
}
I would like to make a reference to the "designer" code page. So I can reference the results in the btn click below:
namespace WindowsFormsApp1
{
public partial class dataBase : Form
{
List<Information> people = new List<Information>();
private personalInfo personal = new personalInfo();
public dataBase()
{
InitializeComponent();
}
public void searchBtn_Click(object sender, EventArgs e)
{
dataAccess db = new dataAccess();
people = db.GetPeople(accountNumber.Text);
ListBoxPeople.DataSource = people;
ListBoxPeople.DisplayMember = "FullInfo";
//Would like to references here from info.cs
}
You seem to be dealing with Windows Forms here, as your main class is a Form. To start things off, I would like to recommend against giving Forms names that are completely unrelated to them. I have the habit of naming the main forms of my applications MainForm, but you could also use, for example, MyAppForm (the name of your application plus the word Form).
Setting that aside, if you need to access a control on your form (such as a TextBox), I recommend that you do so within the Form class itself, unless you have an excellent reason to do so. You will not be able to reference things from outside the form class (as controls are Private), and even if you write a method to pull the controls from your Form, you won't be able to access them (they will be on a different thread), unless you implement an algorithm to get around that.
Therefore, I suggest that you move your GetInfo method to your form class. Notice that that class is a partial class, that means you can create a new class file with the same class name and it will extend your form class, better organizing things (this is what Designer code generation does, hence why you're not supposed to alter things on the Designer file).
Edit: Additionally, as suggested above, if the context of your form doesn't suit your method, you can also pass the data required by a control via an extra public acessible method. That extra method can be called by your Form event, for example.
Note: Be sure to define the class as partial on the other file as well, if you intend to do this.

MS-Access -> OLEDB -> DataTable -> DataGridView memory leak

I'm writing a thick client to an MS-Access(2016) database.
One of my forms retrieves data from the database on form loading into a datagridview. The issue is that after closing this form, the memory usage doesnt drop back to idle. App uses about 20mb before opening this form, after is about 200mb, and after closing the form pretty much stays at 200mb. But if i open it again it will consume an additional 200mb.
I'm using using block almost everywhere, tried explicitly nulling the datatable, call garbage collector, but nothing helps.
//This is the funcion being called on Form load event
public static DataTable oledb_rs(string command)
{
using (OleDbConnection conn = new OleDbConnection())
{
conn.ConnectionString = Connection.ConnStr();
conn.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = command;
using (OleDbDataAdapter rs = new OleDbDataAdapter(cmd))
{
using (DataTable dt = new DataTable())
{
rs.Fill(dt);
return dt;
}
}
}
}
}
//The Form load event
using (DataTable megalldt = Connection.oledb_rs("SELECT * FROM Megallapitasok"))
{
dataGridView1.DataSource = megalldt;
}
//The form close event
dataGridView1.Dispose();
this.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();
GC.Collect();
DataGridView.Dispose() doesn't do much about the datasource (and its underlying data), it's more focused on disposing graphical (GDI+) objects, visual columns, cells, pens, brushes, etc. But it has a reference on it.
So, what you need to reduce memory is ensure nothing holds a reference to the DataTable (the instance you created) anymore. There are many ways to do it, it depends how your objects are created, what instance references what, how they go out of scope, etc.
The most simple solution is to close the 2nd form, then, dataGridView1 will not be referenced anymore (it was referenced by the 2nd form), same for its DataSource instance. Then you can run your GC collection code.

"Input string was not in a correct format."

I am working on a project in which I have a form through which I can edit a question available in a list view. Whenever I select a row from the list view and click on the 'modify' button, the text boxes above the list view load the question and its options.
This means that when I select a row in the list view and click on the 'modify' button, the question loads itself into the text boxes. I edit the question there and click on 'save' to save changes, but I am not able to access the data in the text boxes. It says {"Input string was not in a correct format."}.
My code of the form frmFormWizard's 'edit' button is given below:
frmFormWizard.cs Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Sql;
using System.Data.SqlClient;
namespace SurveyBuilder
{
public partial class frmFormWizard : Form
{
int intPanelNumber = 1;
Boolean blnCancel = false;
//int intFlag = 1;
public frmFormWizard()
{
InitializeComponent();
}
...
private void btnEditTwoOrMoreOptions_Click(object sender, EventArgs e)
{
int QuestionID;
string sql;
QuestionID = Convert.ToInt32(lvTwoOrMoreOptions.SelectedItems[0].Text.ToString());
{
SqlConnection cn = new SqlConnection();
SqlCommand rs = new SqlCommand();
SqlDataReader sdr = null;
clsConnection clsCon = new clsConnection();
clsCon.fnc_ConnectToDB(ref cn);
sql = "";
sql += "SELECT * FROM SurveyQuestionLog WHERE SurveyQuestionLog.QuestionLogID = "+ QuestionID +"";
//sql += "SELECT * FROM SurveyQuestionLog";
rs.Connection = cn;
rs.CommandText = sql;
sdr = rs.ExecuteReader();
while (sdr.Read())
{
txtTwoOrMoreQuestions.Text = (string)sdr["Question"];
txtOption1.Text = (string)sdr["Choice1"];
...
}
sdr.Close();
rs = null;
cn.Close();
}
}
Whenever I try to compile the code it says "{"Input string was not in a correct format."}" and this error is shown on the following line:
QuestionID = Convert.ToInt32(lvTwoOrMoreOptions.SelectedItems[0].Text.ToString());
Please let me know what I am doing wrong.
It looks like some space include in the text.
Use
lvTwoOrMoreOptions.SelectedItems[0].Text.ToString().Trim()
and convert to int32.
hope this code will solve you
From comments
if your ListView is in report mode (i.e. it looks like a grid) then you will need the SubItems property. lvTwoOrMoreOptions.SelectedItems gets you each items in the list view - SubItems gets you the columns. So lvTwoOrMoreOptions.SelectedItems[0].SubItems[0] is the first column value,
Please change your code like below.
int QuestionID;
bool IsIntValue = Int32.TryParse("YOUR-VARIABLE", out QuestionID);
if (IsIntValue)
{
// YOUR CODE HERE
}
Hope i will be help.
whenever i try to compile the code it says "{"Input string was not in a correct format."}"
This error won't come on compiling.
Now the error comese because you are trying to parse an invalid string to integer. To do it in a safe manner, you should do it like this
int questionID;
if(int.TryParse(vTwoOrMoreOptions.SelectedItems[0].Text.ToString(),out questionID))
{
//success code
}
else
{
//failure code
}
You might be trying to access a control inside a control, maybe a GridView or DetailsView.
Try using something like this:
empsalary = Convert.ToInt32(((TextBox)DetailsView1.Rows[1].Cells[1].Controls[0]).Text);
It looks that whatever that text is containing some characters which cannot be converted to integer like space, letters, special characters etc. Check what is coming through dropdown as below
lvTwoOrMoreOptions.SelectedItems[0].Text.ToString();
and see if that is the case.

Linking Textboxes to a dataset using a BindingSource

This is the section of the form I am working on:
The following code links the BindingNavigator to the dataset using a bindingSource. Can I use this binding source to hook up the two text boxes to the data?
Do I simply need to use a property of the textboxes or is this more involved?
i.e when the form loads the first record's fields "Work Phrase" and "Description" will be displayed and when I scroll using the navigator the values in these boxes will change accordingly.
public partial class uxRevisionHelperForm : Form
{
public SqlCeConnection conn = new SqlCeConnection(ConfigurationManager.ConnectionStrings["WindFormAppRevisionHelper.Properties.Settings.DefinitionsDBConnectionString"].ConnectionString);
BindingSource definitionsBindingSource = new BindingSource();
public uxRevisionHelperForm()
{
InitializeComponent();
uxDescriptionTextBox.AutoSize = true;
this.hookUpBindingNavigator();
}
public void hookUpBindingNavigator()
{
SqlCeDataAdapter da = new SqlCeDataAdapter(new SqlCeCommand("Select * From tb_Definitions",conn));
DataSet ds = new DataSet("Helper");
ds.Tables.Add("DefinitionsTable");
da.Fill(ds.Tables["DefinitionsTable"]);
// Assign the BindingSource.
this.uxBindingNavigator.BindingSource = this.definitionsBindingSource;
this.definitionsBindingSource.DataSource = ds.Tables["DefinitionsTable"];
}
Try using the DataBinding collection of the textboxes.
Something like this:
uxDescriptionTextBox.DataBindings.Add("Text",
definitionsBindingSource,
fieldInTable);
Have added the full source code (highlighting exactly your requirement) here - http://sdrv.ms/NyXHdu. Download > Open the solution in VS2010 > Hit F5
[Update]
Double click on Form.cs designer and observe the productListBindingSource. It bound to a custom object - The ProductList class
Then see the properties of the TextBoxes & ComboBox and observe the DataBindings > Text property. They are bound to the productListBindingSource's individual item. See Image below.
Courtsey - http://www.apress.com/9781590594391/ [Chapter 8]

Categories

Resources