Related
I'm a newbie in Visual Studio and I want to make a database system that allows the user to insert, update, delete and search data using a Windows Forms application.
I already watched 3 tutorial how but I'm getting the same error. when I delete my ExecuteNonQuery() call, it doesn't have any error but the data I entered into my textboxes is not inserted into my database. When I put it back I'm getting this kind of error
ERROR:
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.SqlClient;
using System.Threading.Tasks;
namespace EaglePlannersDatabase
{
public partial class Form1 : Form
{
SqlConnection connection = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Adrian\Documents\EaglePlannersDataBase.mdf;Integrated Security=True;Connect Timeout=30");
public Form1()
{
InitializeComponent();
}
private void InsertButton_Click(object sender, EventArgs e)
{
connection.Open();
SqlCommand cmd = new SqlCommand("Insert Into EAGLEPLANNERS(policy number,plan type,renewal date,name,age,address,birthday,email,home/office number,mode of payment,amount) values (#policy number,#plan type,#renewal date,#name,#age,#address,#birthday,#email,#home/office number,#mode of payment,#amount)", connection);
cmd.Parameters.AddWithValue("#policy number", int.Parse(policyNumbertxtbox.Text));
cmd.Parameters.AddWithValue("#plan type", planTypetxtbox.Text);
cmd.Parameters.AddWithValue("#renewal date", int.Parse(renewalDatetxtbox.Text));
cmd.Parameters.AddWithValue("#name", nametxtbox.Text);
cmd.Parameters.AddWithValue("#age", int.Parse(agetxtbox.Text));
cmd.Parameters.AddWithValue("#address", addresstxtbox.Text);
cmd.Parameters.AddWithValue("#birthday", int.Parse(birthdaytxtbox.Text));
cmd.Parameters.AddWithValue("#email", (emailtxtbox.Text));
cmd.Parameters.AddWithValue("#home/office number", int.Parse(homeofficetxtbox.Text));
cmd.Parameters.AddWithValue("#mode of payment", (modeofpaymenttxtbox.Text));
cmd.Parameters.AddWithValue("#amount", int.Parse(amounttxtbox.Text));
cmd.ExecuteNonQuery();
connection.Close();
policyNumbertxtbox.Text = "";
planTypetxtbox.Text = "";
renewalDatetxtbox.Text = "";
nametxtbox.Text = "";
agetxtbox.Text = "";
addresstxtbox.Text = "";
birthdaytxtbox.Text = "";
emailtxtbox.Text = "";
homeofficetxtbox.Text = "";
modeofpaymenttxtbox.Text = "";
amounttxtbox.Text = "";
MessageBox.Show("Record inserted successfully!");
}
}
}
As a newbie, getting the pieces working first, then applying to the user interface I would apply second. I will try to summarize each piece. First your connection itself looked strange as others have pointed out. I would try to first make sure the connection itself works before applying any attempt at sql insert/update/delete going on. So you might try
SqlConnection connection = new SqlConnection(
#"Data Source (LocalDB)\MSSQLLocalDB; AttachDbFilename=C:\Users\Adrian\Documents\EaglePlannersDataBase.mdf;
Integrated Security=True;
Connect Timeout=30" );
private void TestConnect()
{
if( connection.Open() )
// great, you have a good connection
connection.Close();
else
// message to yourself why a failed connection and fix it...
}
Once you know your connection is good, then on to your sql-insert. Having good column names is important. Dont try to be fancy with human readable with spaces types of column names, just causes headaches. Use simple and direct as others have pointed out in prior comments. Also, when parameterizing, I have tried to always slightly alter the insert/update/delete parameters with a "p" prefix indicating the PARAMETER FOR the column, such as
insert into SomeTable ( oneColumn, secondCol ) values ( #pOneColumn, #pSecondCol )
just to avoid bad confusion. If an error comes out via "oneColumn" vs "pOneColumn" in the message, you KNOW which thing is at fault. The column itself does not work, or the specific parameter/value being supplied.
Next, readability of your SQL statements, especially as they get longer. Use spaces and I typically use a leading "#" before the quoted sql command to allow for line continuations as I edited your previous answer. So the same above insert would be written more like
var cmd = new SqlCommand(
#"insert into SomeTable
( oneColumn,
secondCol
)
values
( #pOneColumn,
#pSecondCol
)", connection );
So if you ever needed to add additional columns (or remove), you can see the paired set of insert columns vs parameters much easier.
Now the testing. Don't try to work off some user-entered values, put in known VALID values so you dont have to worry about user entered values. Get the command to WORK, then pull values from interface later. (continuing from above sample)
cmd.Parameters.AddWithValue("#pOneColumn", 17 );
cmd.Parameters.AddWithValue("#pSecondCol", "some Text");
Then try to execute that and make sure IT works. Once it does, THEN start pulling from your user interface
cmd.Parameters.AddWithValue("#pOneColumn", int.Parse( yourTextControl.Text ));
cmd.Parameters.AddWithValue("#pSecondCol", anotherTextControl.Text );
Find your mistakes BEFORE you let any human interaction get into and screw-up the rest of what you think SHOULD work.
Note, if you make public properties to your view models such as
public int someAge {get; set;}
and then set the bindings of the data entry control in the screen to this someAge property, it will only allow a numeric entry to be entered and will otherwise have a value of zero if someone tries to put in text. Similarly if you are dealing with dates, and if date/time, always use datetime fields for querying purposes vs formatted date as a text field. You will thank yourself in the future when querying for things within date range periods. HTH
Finally,try to avoid using AddWithValue. Instead, properly identify the expected data type as described in the linked article. I just left original context to your code for testing and debug researching purposes.
This would be the possible answer on your question, what I have done here, first I changed your connection string by removing AttachDbFilename attribute, and replace that by adding of Initial Catalog attribute where I set the name of your database.
Next thing, I declared variables where the values from textboxes will be stored, these values of variables will be our parameters, this is not necessary to do, it is just my own style, you can keep as you done.
I have seen also, that you are not using try/catch/finally block and you are closing the connection in the same part of code where you opening the connection, and maybe that is the reason why your values are not being stored into the table, so I decided to round your code within that block. If you don't know what is try/catch/finally block you can read the documentation here . We are opening the connection and do all operations on database in try block, in catch block we are catching all errors that might be caused in our application and in finally we are closing the connection. You will also notice that I created additional check, where I checking the result of ExecuteNonQuery() method, and if result of ExecuteNonQuery method is equals to 1 - records is inserted successfully, otherwise it fails.
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.SqlClient;
using System.Threading.Tasks;
namespace EaglePlannersDatabase
{
public partial class Form1 : Form
{
SqlConnection connection = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;Initial Catalog=EaglePlannersDataBase;Integrated Security=True;Connect Timeout=30");
public Form1()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void InsertButton_Click(object sender, EventArgs e)
{
int policyNumber = Convert.ToInt32(policyNumbertxtbox.Text);
string planType = planTypetxtbox.Text;
int renewalDate = Convert.ToInt32(renewalDatetxtbox.Text);
string name = nametxtbox.Text;
int age = Convert.ToInt32(agetxtbox.Text);
string address = addresstxtbox.Text;
int birthday = Convert.ToInt32(birthdaytxtbox.Text);
string email = emailtxtbox.Text;
int homeOfficeNumber = Convert.ToInt32(homeofficetxtbox.Text);
string modeOfPayment = modeofpaymenttxtbox.Text;
int amount = Convert.ToInt32(amounttxtbox.Text);
try
{
connection.Open();
SqlCommand cmd = new SqlCommand("Insert Into tbl1 (PolicyNumber,planType,renewalDate,name,age,address,birthday,email,homeOfficeNumber,modeOfPayment,amount) values (#PolicyNumber,#planType,#renewalDate,#name,#age,#address,#birthday,#email,#homeOfficeNumber,#modeOfPayment,#amount)", connection);
cmd.Parameters.AddWithValue("#PolicyNumber",policyNumber);
cmd.Parameters.AddWithValue("#planType",planType);
cmd.Parameters.AddWithValue("#renewalDate",renewalDate);
cmd.Parameters.AddWithValue("#name",name);
cmd.Parameters.AddWithValue("#age",age);
cmd.Parameters.AddWithValue("#address",address);
cmd.Parameters.AddWithValue("#birthday",birthday);
cmd.Parameters.AddWithValue("#email",email);
cmd.Parameters.AddWithValue("#homeOfficeNumber",homeOfficeNumber);
cmd.Parameters.AddWithValue("#modeOfPayment",modeOfPayment);
cmd.Parameters.AddWithValue("#amount",amount);
int result = cmd.ExecuteNonQuery();
if(result == 1)
{
MessageBox.Show("Record Inserted Successfully!");
policyNumbertxtbox.Text = "";
planTypetxtbox.Text = "";
renewalDatetxtbox.Text = "";
nametxtbox.Text = "";
agetxtbox.Text = "";
addresstxtbox.Text = "";
birthdaytxtbox.Text = "";
emailtxtbox.Text = "";
homeofficetxtbox.Text = "";
modeofpaymenttxtbox.Text = "";
amounttxtbox.Text = "";
}
else
{
MessageBox.Show("Something went wrong!");
}
}
catch(SqlException ex)
{
MessageBox.Show("We have found error with operation on database: " + ex.Message);
}
catch(Exception ex)
{
MessageBox.Show("We have found error in your code: " + ex.Message);
}
finally
{
connection.Close();
}
}
}
}
here's my new 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.SqlClient;
using System.Threading.Tasks;
namespace EaglePlannersDatabase
{
public partial class Form1 : Form
{
SqlConnection connection = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Adrian\Documents\EaglePlannersDataBase.mdf;Integrated Security=True;Connect Timeout=30");
public Form1()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void InsertButton_Click(object sender, EventArgs e)
{
connection.Open();
SqlCommand cmd = new SqlCommand(
#"Insert Into tbl1
( PolicyNumber,
planType,
renewalDate,
name,
age,
address,
birthday,
email,
homeOfficeNumber,
modeOfPayment,
amount )
values
( #PolicyNumber,
#planType,
#renewalDate,
#name,
#age,
#address,
#birthday,
#email,
#homeOfficeNumber,
#modeOfPayment,
#amount )", connection);
cmd.Parameters.AddWithValue("#PolicyNumber", int.Parse(policyNumbertxtbox.Text));
cmd.Parameters.AddWithValue("#planType", planTypetxtbox.Text);
cmd.Parameters.AddWithValue("#renewalDate", int.Parse(renewalDatetxtbox.Text));
cmd.Parameters.AddWithValue("#name", nametxtbox.Text);
cmd.Parameters.AddWithValue("#age", int.Parse(agetxtbox.Text));
cmd.Parameters.AddWithValue("#address", addresstxtbox.Text);
cmd.Parameters.AddWithValue("#birthday", int.Parse(birthdaytxtbox.Text));
cmd.Parameters.AddWithValue("#email", (emailtxtbox.Text));
cmd.Parameters.AddWithValue("#homeOfficeNumber", int.Parse(homeofficetxtbox.Text));
cmd.Parameters.AddWithValue("#modeOfPayment", (modeofpaymenttxtbox.Text));
cmd.Parameters.AddWithValue("#amount", int.Parse(amounttxtbox.Text));
cmd.ExecuteNonQuery();
connection.Close();
policyNumbertxtbox.Text = "";
planTypetxtbox.Text = "";
renewalDatetxtbox.Text = "";
nametxtbox.Text = "";
agetxtbox.Text = "";
addresstxtbox.Text = "";
birthdaytxtbox.Text = "";
emailtxtbox.Text = "";
homeofficetxtbox.Text = "";
modeofpaymenttxtbox.Text = "";
amounttxtbox.Text = "";
MessageBox.Show("Record Inserted Successfully!");
}
}
}
here's my database
Here's what I'm trying to accomplish ... At the click of a button, I want to:
Copy existing data of the live "users" table to "old_users" table for backup purposes
Truncate the existing "new_users" table to prepare it to accept new rows
Parse through a CSV file to insert data into the "new_users" table
Truncate the existing "users" table and then copy data of the "new_users" table to "users" table
I am not a daily programmer and haven't created a program in a very long time. But I've piece-mealed some code together to get something that kinda works. Below is my current code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.VisualBasic.FileIO;
using Renci.SshNet;
using Renci.SshNet.Common;
using MySql.Data.MySqlClient;
namespace ValidationImport
{
public partial class ValiationImport : Form
{
public ValiationImport()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnImportToDatabase_Click(object sender, EventArgs e)
{
try
{
using (var client = new SshClient("1.1.1.1", "[username]", "[password]")) // establishing ssh connection to server where MySql is hosted
{
client.Connect();
if (client.IsConnected)
{
var portForwarded = new ForwardedPortLocal("127.0.0.1", 3306, "127.0.0.1", 3306);
client.AddForwardedPort(portForwarded);
portForwarded.Start();
using (MySqlConnection con = new MySqlConnection("SERVER=localhost;PORT=3306;UID=[username];PASSWORD=[password];DATABASE=[dbname]")) // MySql database credentials
{
con.Open();
// Copying over the users table (with structure and indexes) to the old_users table. Truncating the new_users table to prepare for new data.
using (MySqlCommand cmd = new MySqlCommand("DROP TABLE test_old_users; CREATE TABLE test_old_users LIKE test_users; INSERT test_old_users SELECT * FROM test_users; TRUNCATE TABLE test_new_users;", con))
{
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
string fileName = "";
// Select the Validation file to import
OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == DialogResult.OK)
fileName = dlg.FileName;
if (fileName != "")
{
using (TextFieldParser parser = new TextFieldParser(fileName))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters("|");
parser.ReadLine(); // Skip the first row of field title headers
while (!parser.EndOfData)
{
//Copy each row individually over to the MySql table
string[] row = parser.ReadFields();
using (MySqlCommand cmd = new MySqlCommand("INSERT INTO test_new_users (`Indv Id`, `Last Name`, `First Name`, `Middle Name`, `Birth date`, `Indv Addr Line 1`, `Indv Addr Line 2`, `Indv Addr Line 3`, `Indv City`, `Indv State`, `Indv Zip`, `Indv Country`, `Local Id`, `Local Name`, `Local User Id`, `Uniserv Id`, `Uniserv Name`, `Uniserv User Id`, `Chapter Name`, `Chapter User Id`, `Employer Id`, `Employer Name`, `Work Location Id`, `Work Location Name`, `Work Location User Id`, `Group Id`, `Group Name`, `Group Type Id`, `Group Type Name`, `SEA P01`, `Home Phone`, `Home Phone principal Ind`, `Home Phone Unlisted Ind`, `Mobile Phone`, `Mobile Phone Principal Ind`, `Mobile Phone Unlisted Ind`, `Home Email`, `Home Email Principal Ind`, `Work Email`, `Work Email Principal Ind`, `Other Email`, `Other Email Principal Ind`) VALUES (#IndvId, #LastName, #FirstName, #MiddleName, #BirthDate, #IndvAddrLine1, #IndvAddrLine2, #IndvAddrLine3, #IndvCity, #IndvState, #IndvZip, #IndvCountry, #LocalId, #LocalName, #LocalUserId, #UniservId, #UniservName, #UniservUserId, #ChapterName, #ChapterUserId, #EmployerId, #EmployerName, #WorkLocationId, #WorkLocationName, #WorkLocationUserId, #GroupId, #GroupName, #GroupTypeId, #GroupTypeName, #SEAP01, #HomePhone, #HomePhonePrincipalInd, #HomePhoneUnlistedInd, #MobilePhone, #MobilePhonePrincipalInd, #MobilePhoneUnlistedInd, #HomeEmail, #HomeEmailPrincipalInd, #WorkEmail, #WorkEmailPrincipalInd, #OtherEmail, #OtherEmailPrincipalInd);", con))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#IndvId", row[0]);
cmd.Parameters.AddWithValue("#LastName", row[1]);
cmd.Parameters.AddWithValue("#FirstName", row[2]);
cmd.Parameters.AddWithValue("#MiddleName", row[3]);
cmd.Parameters.AddWithValue("#BirthDate", row[4]);
cmd.Parameters.AddWithValue("#IndvAddrLine1", row[5]);
cmd.Parameters.AddWithValue("#IndvAddrLine2", row[6]);
cmd.Parameters.AddWithValue("#IndvAddrLine3", row[7]);
cmd.Parameters.AddWithValue("#IndvCity", row[8]);
cmd.Parameters.AddWithValue("#IndvState", row[9]);
cmd.Parameters.AddWithValue("#IndvZip", row[10]);
cmd.Parameters.AddWithValue("#IndvCountry", row[11]);
cmd.Parameters.AddWithValue("#LocalId", row[12]);
cmd.Parameters.AddWithValue("#LocalName", row[13]);
cmd.Parameters.AddWithValue("#LocalUserId", row[14]);
cmd.Parameters.AddWithValue("#UniservId", row[15]);
cmd.Parameters.AddWithValue("#UniservName", row[16]);
cmd.Parameters.AddWithValue("#UniservUserId", row[17]);
cmd.Parameters.AddWithValue("#ChapterName", row[18]);
cmd.Parameters.AddWithValue("#ChapterUserId", row[19]);
cmd.Parameters.AddWithValue("#EmployerId", row[20]);
cmd.Parameters.AddWithValue("#EmployerName", row[21]);
cmd.Parameters.AddWithValue("#WorkLocationId", row[22]);
cmd.Parameters.AddWithValue("#WorkLocationName", row[23]);
cmd.Parameters.AddWithValue("#WorkLocationUserId", row[24]);
cmd.Parameters.AddWithValue("#GroupId", row[25]);
cmd.Parameters.AddWithValue("#GroupName", row[26]);
cmd.Parameters.AddWithValue("#GroupTypeId", row[27]);
cmd.Parameters.AddWithValue("#GroupTypeName", row[28]);
cmd.Parameters.AddWithValue("#SEAP01", row[29]);
cmd.Parameters.AddWithValue("#HomePhone", row[30]);
cmd.Parameters.AddWithValue("#HomePhonePrincipalInd", row[31]);
cmd.Parameters.AddWithValue("#HomePhoneUnlistedInd", row[32]);
cmd.Parameters.AddWithValue("#MobilePhone", row[33]);
cmd.Parameters.AddWithValue("#MobilePhonePrincipalInd", row[34]);
cmd.Parameters.AddWithValue("#MobilePhoneUnlistedInd", row[35]);
cmd.Parameters.AddWithValue("#HomeEmail", row[36]);
cmd.Parameters.AddWithValue("#HomeEmailPrincipalInd", row[37]);
cmd.Parameters.AddWithValue("#WorkEmail", row[38]);
cmd.Parameters.AddWithValue("#WorkEmailPrincipalInd", row[39]);
cmd.Parameters.AddWithValue("#OtherEmail", row[40]);
cmd.Parameters.AddWithValue("#OtherEmailPrincipalInd", row[41]);
cmd.ExecuteNonQuery();
}
}
}
}
// Copying over the new_users table (with structure and indexes) to the users table.
using (MySqlCommand cmd = new MySqlCommand("DROP TABLE test_users; CREATE TABLE test_users LIKE test_new_users; INSERT test_users SELECT * FROM test_new_users;", con))
{
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
con.Close();
}
client.Disconnect();
}
else
{
Console.WriteLine("Client cannot be reached...");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
It's all "working" ... except I get an error when in debug mode in visual studio. Something about how it's taking too long to process. Oh, just so you know, there's around 38,000 rows in the CSV file that has to be inserted into the table.
If you have any suggestions or new code for me to try out, I'd greatly appreciate it! Thank you!
In many scenarios where you end up looping over data running the same queries repeatedly for different data, you can help speed things up by preparing the query once, before looping begins.
using (var cn = new MySqlConnection(...))
using (var cmd = cn.CreateCommand())
{
// Setup command
cmd.CommandText = "Some query";
var param1 = cmd.Parameters.Add("#paramName1", MySQLDbType.sometype);
var param2 = cmd.Parameters.Add("#paramName2", MySQLDbType.sometype);
cmd.Prepare();
// get data
// loop over data
foreach(var d in data)
{
param1.Value = d.somevalue;
param2.Value = d.anothervalue;
cmd.ExecuteNonQuery();
}
}
You can also address the parameters by index, like cmd.Parameters[0].Value.
Preparing the statement in this manner reduces the overhead of the work done to parse the query itself every iteration.
In one situation I had to deal with, I found the best solution was to combine the above with an INSERT query that used multiple values lists, of the form INSERT INTO X(a,b,c) VALUES (?,?,?),(?,?,?),(?,?,?). It made the actual implementation much more complicated (having to appropriately handle the "leftovers" at the end that would not fill all values lists), and relied on addressing the parameters by index; but did make a difference.
Edit: pseudo code to handle ssh connection closing on you
connect = true
Open datasource
while (data remains)
{
if (connect)
{
init ssh client
init mysql connection
init mysql command
connect = false
}
while (data remains and enough time remaining)
{
get next data
set command parameters
execute command
}
if (not enough time remaining)
{
close current connection and client
connect = true
}
}
I'm trying to read a CSV file into a table that I have created in Visual Studio. I want to validate the values in the file to see if they are correct, if all the values pass the checks, it will go into the table. If any values are not correct, an error report will be created using a JSON file.
I have already got some test data ready but I'm not sure how to separate the correct data from the incorrect data after the checker are complete.
public partial class NHSBatchChecker : Form
{
public NHSBatchChecker()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = #"C:\Users\wy6282\Desktop\VS\NHSBATCHCHECKER\Test.txt"; // Start in C: drive
openFileDialog1.Title = "Browse Text Files";
openFileDialog1.RestoreDirectory = true;
openFileDialog1.DefaultExt = "txt"; // Extension of file is txt only
openFileDialog1.Filter = "Text|*.txt||*.*"; //Only text files allowed
openFileDialog1.CheckFileExists = true; // Error message if file does not exist
openFileDialog1.CheckPathExists = true; // Error message if invalid file path
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string connectionstring;
SqlConnection cnn;
connectionstring = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\wy6282\Desktop\VS\NHSBATCHCHECKER\nhsBatchChecker\Results.mdf;Integrated Security=True";
cnn = new SqlConnection(connectionstring);
cnn.Open();
SqlCommand command;
SqlDataAdapter adaper = new SqlDataAdapter();
string sql = "";
sql = "Insert into Results(NHS Number, Date of Birth, First Name, Last Name, Title, Gender) values()";
command = new SqlCommand(sql, cnn);
adaper.InsertCommand = new SqlCommand(sql, cnn);
adaper.InsertCommand.ExecuteNonQuery();
command.Dispose();
cnn.Close();
How do I add my valid records into the sql table?
you're trying to do too much in one go.
rule number 1: always split your problem into manageable junks:
read data from CSV.
filter incorrect data
save filtered data to database.
Now you have 3 distinct pieces of work to focus on.
Reading data from a CSV is trivial, there are many libraries that can help with that. Do a bit of research and pick one.
Create a class which holds the properties you need for validation checks and also those you want saved in the database.
Your goal is to create a list of these objects, one per row in csv. Of course, you may not be able to read everything in one go depending on how much data your csv holds, but you can pick a library which can deal with whatever size you have.
Now you have a list of objects. Write an algorithm which determines what is valid and what not, based on the rules you need. Your goal here is to end up with a possibly smaller list of the same objects, chucking out the invalid ones.
Save whatever is left in the database.
You need to start thinking about how you organize you code, don't just throw everything into the Click event of a button. You can create a model class to hold your objects, maybe create a separate class library where you can put your csv reading method.
Another class library perhaps for your filtering algorithm(s).
Your Click event should be fairly slim and only call library methods when it needs to do something. This is separation of concerns or SOC, which is a Solid Principle.
I am not sure how you plan to validate the datapoints, but the code below shows how to pull data from a CSV and load it into a SQL Server table.
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.IO;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Configuration;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string server = "EXCEL-PC\\EXCELDEVELOPER";
string database = "AdventureWorksLT2012";
string SQLServerConnectionString = String.Format("Data Source={0};Initial Catalog={1};Integrated Security=SSPI", server, database);
string CSVpath = #"C:\Users\Ryan\Documents\Visual Studio 2010\Projects\Bulk Copy from CSV to SQL Server Table\WindowsFormsApplication1\bin"; // CSV file Path
string CSVFileConnectionString = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};;Extended Properties=\"text;HDR=Yes;FMT=Delimited\";", CSVpath);
var AllFiles = new DirectoryInfo(CSVpath).GetFiles("*.CSV");
string File_Name = string.Empty;
foreach (var file in AllFiles)
{
try
{
DataTable dt = new DataTable();
using (OleDbConnection con = new OleDbConnection(CSVFileConnectionString))
{
con.Open();
var csvQuery = string.Format("select * from [{0}]", file.Name);
using (OleDbDataAdapter da = new OleDbDataAdapter(csvQuery, con))
{
da.Fill(dt);
}
}
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(SQLServerConnectionString))
{
bulkCopy.ColumnMappings.Add(0, "MyGroup");
bulkCopy.ColumnMappings.Add(1, "ID");
bulkCopy.ColumnMappings.Add(2, "Name");
bulkCopy.ColumnMappings.Add(3, "Address");
bulkCopy.ColumnMappings.Add(4, "Country");
bulkCopy.DestinationTableName = "AllEmployees";
bulkCopy.BatchSize = 0;
bulkCopy.WriteToServer(dt);
bulkCopy.Close();
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
}
}
I've a form opened which is has loaded some sort of data (like username, CNIC, Contact no, etc etc) in Check boxes, now I want to update the data in such manner that I simply change the text in the text boxes and click on the save changes to save it. I've tried it but I am not able to do it in correct manner.
Let me show you how I've coded, the code I did in frmViewformList savechanges button is :
private void btnSaveChanges_Click(object sender, EventArgs e)
{
string sql;
string UserName;
UserName = txtUserName.Text; // saving data loaded on run time to UserName
sql = "";
sql += "UPDATE UserLogin";
sql += "SET Name = "+ //how to access data I've changed in TextBox after loading +"";
sql += "WHERE Name= " + //how to access data which was in text box right after loading + ""; //
}
I am a bit confused about how to refer to data, like the name already in the text box or the name which I have changed and how to write it in SQL query...
This question is a bit confusing, I know. Let me explain; the form is loaded, there are text boxes which is being populated with the data in database on load event, I change the data in text boxes and save on click so that the update query runs and changes the data in database as well.
I'm not able to create logic here how to do this, can any one help me out, I am sorry I am a new developer of C# that's why I am a bit confused.
You should use Sql Parameters in order to avoid SQL Injection which could leave your database vulnerable to malicious exploitation.
It's a good idea to separate the logic for performing the update to the logic where you create your query so you don't have to repeat code and so that you can maintain your code easier.
Here is an example you can reference:
public void DoWork()
{
// Build Query Use #Name Parameters instead of direct values to prevent SQL Injection
StringBuilder sql = new StringBuilder();
sql.Append("UPDATE UserLogin");
sql.Append("SET Name = #UpdatedName");
sql.Append("WHERE Name = #Name");
// Create parameters with the value you want to pass to SQL
SqlParameter name = new SqlParameter("#Name", "whatEverOldNameWas");
SqlParameter updatedName = new SqlParameter("#UpdatedName", txtUserName.Text);
Update(sql.ToString(), new [] { name, updatedName });
}
private static readonly string connectionString = "Your connection string"
private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
public static int Update(string sql, SqlParameter[] parameters)
{
try
{
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = connectionString;
using (DbCommand command = factory.CreateCommand())
{
command.Connection = connection;
command.CommandText = sql;
foreach (var parameter in parameters)
{
if (parameter != null)
command.Parameters.Add(parameter);
}
connection.Open();
return command.ExecuteNonQuery();
}
}
}
catch (Exception)
{
throw;
}
}
You will want to strip all ', ", and ` characters out of your input so that people can't inject SQL. When you do SET Name = " +, you'll want to actually wrap whatever you're including in quotes because it's a string: SET Name = '" + UserName "' " +...
This is probably best done using
string.Format("UPDATE UserLogin SET Name = '{0}' WHERE Name = '{1}'", UserName, FormerUserName);
Then you will execute your query by using System.Data.SqlClient; and then work with SqlConnection to establish a connection to the server, and execute a SqlCommand of some kind; take a look at: http://www.codeproject.com/Articles/4416/Beginners-guide-to-accessing-SQL-Server-through-C
The following is a code snippet to insert data into database using ADO.NET and assuming SQL Server database.
At the top of your .cs file you should have.
using System.Data.SqlClient; // for sql server for other data bases you should use OleClient instead.
And inside your button click event you could put the following.
// to know how to get the right connection string please check this site: http://www.connectionstrings.com
string connString = "database connection string here";
using (SqlConnection con = new SqlConnection(connString))
{
con.Open();
//insert text into db
string sql_insert = "INSERT INTO ....."; // Use parameters here.
SqlCommand cmd_insert = new SqlCommand(sql_insert, con);
int rowsAffected = cmd_insert.ExecuteNonQuery();
}
Hopefully this is enough to get you started.
I am trying to write a program which creates a .csv file from an Access table. I'm not sure how to do this and everything I've found while researching this is how to do the opposite, creating an Access table from a .csv file.
So far, I have created a windows forms application that allows the user to select a data path to the access directory (.mdb) and then after pushing the "Go" button, a list of the tables in the directory is shown in a listbox.
What I need to do next, which I have no idea how to, is allow the user to select one of the tables, which would then create a .csv file from the selected table. Here is my code so far:
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.OleDb;
using System.Data.Common;
namespace TranslatorHelper
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnPath_Click(object sender, EventArgs e)
{
string dialogText = "";
// Show the dialog and get result.
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK) // Test result.
{
dialogText = openFileDialog1.ToString();
dialogText = dialogText.Replace("System.Windows.Forms.OpenFileDialog: Title: , FileName: ", "");
txtDataPath.Text = dialogText;
}
}
private void btnGetTables_Click(object sender, EventArgs e)
{
// Microsoft Access provider factory
DbProviderFactory factory =
DbProviderFactories.GetFactory("System.Data.OleDb");
DataTable userTables = null;
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+txtDataPath.Text;
// We only want user tables, not system tables
string[] restrictions = new string[4];
restrictions[3] = "Table";
connection.Open();
// Get list of user tables
userTables = connection.GetSchema("Tables", restrictions);
}
// Add list of table names to listBox
for (int i = 0; i < userTables.Rows.Count; i++)
lstTables.Items.Add(userTables.Rows[i][2].ToString());
}
private void lstTables_SelectedIndexChanged(object sender, EventArgs e)
{
}
Please offer any advice you can, anything is appreciated, I'm really stuck here.
Perhaps I can shove you in the proper direction:
You have the start, which is the DbConnection. You can then create a DbCommand from that:
DbCommand command = connection.CreateCommand();
From there, you can assign text, such as:
command.CommandText = "SELECT * FROM " + tableName; //you might have to wrap the table name with quotes or square brackets!
Then you can get a reader:
DbDataReader reader = command.ExecuteReader(CommandBehavior.Default);
Once you have the reader, you've got the data, meaning you can then:
DataTable dt = new DataTable("MyNewTable");
dt.Load(reader);
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn dc in row.Columns)
{
if (!String.IsNullOrEmpty(sb.ToString()))
sb.Append(",");
sb.Append(row[dc.ColumnName].ToString());
}
sb.Append("\n");
}
To get the ListBox selection, you could use:
lstTables.SelectedItem.ToString()
That should give you the item, or in your case a table name. Don't forget that certain words are reserved in SQL (and it also depends on which SQL it is), so you might have to be careful using the table name directly in the SQL string for the CommandText parameter.
Also, I would see no need to use a SelectedIndexChanged event handler unless you need to do something immediately upon the user making a selection. If the behavior you want from the user is to make a selection and then click a button to start a process, then it's unnecessary to handle the change.