I have two classes, first name is class 1 to collect your name and family addition to your car. This came from another class that name is car.
This class (car) has two properties, actually I won't get information directly.
For these classes we have two tables as well - first table has relation with class 1, name is qqq and car connected with car.
What's the problem?
In qqq table I have column id_car. When the customer registers himself, his car id should be stored into the qqq table.
I don't know how pass properties with SQL command
Server code:
public class Class1
{
public int id { get; set; }
public string name { get; set; }
public string family { get; set; }
public car car_id { get; set; }
}
public class car
{
public int id { get; set; }
public String name { get; set; }
public String color { get; set; }
}
Client-side code:
SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = sqlcon;
sqlCommand.CommandText = "insert into cars (name , color) values('BMW','gray');";
sqlCommand.ExecuteNonQuery();
SqlCommand sqlCommand1 = new SqlCommand();
sqlCommand1.Connection = sqlcon;
sqlCommand1.CommandText = "insert into qqq (name, family, id_car) values (#name, #family, #car);";
sqlCommand1.Parameters.AddWithValue("#name", textBox1.Text);
sqlCommand1.Parameters.AddWithValue("#family", textBox2.Text);
sqlCommand1.Parameters.AddWithValue("#car", "***MAIN PROBLEM***");
sqlCommand1.ExecuteNonQuery();
The answer is in the code below. There are also several things here that should be improved, which I will call out via the comments:
//You can put several statements in one sql string.
string sql = "
declare #car int;
insert into cars (name , color) values('BMW','gray');
set #car = scope_identity();
insert into qqq (name, family ,id_car) values (#name,#family,#car);";
// Create a new connection object for each call to the database. Really.
// Read this for more info why: https://softwareengineering.stackexchange.com/q/142065/8057
using (var sqlcon = new SqlConnection("connection string here"))
using (var command = new SqlCommand(sql, sqlcon))
{
//AddWithValue can cause certain serious performance problems
// Instead, be specific about the database type and length for the target column.
// I have to guess here, but you can find this info in your database
command.Parameters.Add("#name", SqlDbType.NVarChar, 50).Value = textBox1.Text;
command.Parameters.Add("#family", SqlDbtype.NVarChar, 120).Value = textBox2.Text;
sqlcon.Open();
command.ExecuteNonQuery();
} // The connection will be closed and disposed here, even if an exception is thrown.
// Your original code would have left the connection open if there was an exception.
If you want to be really careful, you'll also add a transaction to that SQL. This way if the second part fails the first part can be rolled back and you don't end up accidentally only doing part of the work.
If you still want the new id_car value for later use in your application, you can further add a select #car; to the end of the SQL string and change ExecuteNonQuery() to ExecuteScalar() to get the value back.
First at all, you can get the last ID if it is a Identity ID (AUTO_INCREMENT) after insert to the table Car. Then past this ID to the qqq table.
Example:
// for MySQL
sqlCommand.CommandText = "INSERT INTO CARS (name , color) VALUES('BMW','gray') OUTPUT INSERTED.ID VALUES(#UserId, #GameId)";
Int32 newId = (Int32) sqlCommand.ExecuteScalar();
// for SQL Server
sqlCommand.CommandText = "INSERT INTO CARS (name , color) VALUES('BMW','gray') VALUES(#UserId, #GameId); SELECT SCOPE_IDENTITY();";
int primaryKey = Convert.ToInt32(sqlCommand.ExecuteScalar());
SqlCommand sqlCommand1 = new SqlCommand();
sqlCommand1.Connection = sqlcon;
sqlCommand1.CommandText = "insert into qqq (name , family ,id_car) values (#name,#family,#car);";
sqlCommand1.Parameters.AddWithValue("#name", textBox1.Text);
sqlCommand1.Parameters.AddWithValue("#family", textBox2.Text);
sqlCommand1.Parameters.AddWithValue("#car", newId); // mysql
sqlCommand1.Parameters.AddWithValue("#car", primaryKey); // sql server
Related
How can I insert my FK_clubID from ClubMember table that references Clubs(clubID)?
I'm using the identity (1,1) on clubID should I add the value for FK_clubID?
public void addclubs(string clubname, DateTime established, byte[] images, string activate)
{
string insertSQL = "INSERT INTO Clubs(club_name,established,image,activate)" + "Values(#club,#esb,#img,#acv)";
Connect();
SqlCommand cmd = new SqlCommand(insertSQL, conn);
cmd.Parameters.AddWithValue("#club", clubname);
cmd.Parameters.AddWithValue("#esb", established);
cmd.Parameters.AddWithValue("#img", images);
cmd.Parameters.AddWithValue("#acv", activate);
cmd.ExecuteNonQuery();
return ;
}
public void addclubmember(string presidentID , string viceID, string secID, string president, string vice, string sec)
{
string updateSQL = "INSERT INTO ClubMember(presidentID,viceID,secID,president,vice,sec) VALUES (#prs,#vice,#sec,#prsn,#vicen,#secn)";
Connect();
SqlCommand cmd = new SqlCommand(updateSQL, conn);
cmd.Parameters.AddWithValue("#prs", presidentID);
cmd.Parameters.AddWithValue("#vice", viceID);
cmd.Parameters.AddWithValue("#sec", secID);
cmd.Parameters.AddWithValue("#prsn", president);
cmd.Parameters.AddWithValue("#vicen", vice);
cmd.Parameters.AddWithValue("#secn", sec);
cmd.ExecuteNonQuery();
return;
}
You need to change the first method to return the ClubID just inserted
public int addclubs(string clubname, DateTime established, byte[] images, string activate)
{
string insertSQL = #"INSERT INTO Clubs(club_name,established,image,activate)
Values(#club,#esb,#img,#acv);
SELECT SCOPE_IDENTITY()";
Connect();
SqlCommand cmd = new SqlCommand(insertSQL, conn);
cmd.Parameters.AddWithValue("#club", clubname);
cmd.Parameters.AddWithValue("#esb", established);
cmd.Parameters.AddWithValue("#img", images);
cmd.Parameters.AddWithValue("#acv", activate);
int newClubID = cmd.ExecuteScalar();
return newClubID;
}
In this way you get back the last identity value inserted using your connection instance. Of course you could add it to your query that updates the members of that club changing the current query to add also this parameter for its column.
Beware that the last inserted identity in your connection could be different if there is a trigger on the club table that inserts data in other tables with identity columns
Unrelated to your current problem I have also two other advices to your code. First, try to use objects to represent Clubs and ClubMembers, it is not clear if you have just a bunch of simple variables here or if you have a more structured way to represent your data models. Second, do not use AddWithValue. This is handy but has many drawbacks both in terms of performances and in terms of reliability. See AddWithValue is Evil
Assuming you have a column in your database table of "ClubMember" named "clubID" which has a foreign key constraint with primary key from "Club" table, this is how you insert the value:
public void addclubmember(string presidentID , string viceID, string secID,
string president, string vice, string sec, string clubID)
{
string updateSQL = "INSERT INTO
ClubMember(presidentID,viceID,secID,president,vice,sec, clubID) VALUES
(#prs,#vice,#sec,#prsn,#vicen,#secn, #clubID)";
Connect();
SqlCommand cmd = new SqlCommand(updateSQL, conn);
cmd.Parameters.AddWithValue("#prs", presidentID);
cmd.Parameters.AddWithValue("#vice", viceID);
cmd.Parameters.AddWithValue("#sec", secID);
cmd.Parameters.AddWithValue("#prsn", president);
cmd.Parameters.AddWithValue("#vicen", vice);
cmd.Parameters.AddWithValue("#secn", sec);
cmd.Parameters.AddWithValue("#clubID", clubID);
cmd.ExecuteNonQuery();
}
i want to parse a CSV file, store it in a list then insert values from that list to a database . Here is the sample of my code.
I'm still learning so if it is not clear then i will explain further. But the idea is to parse the csv file, row by row, and then insert each row in my database. Thank you in advance.
public class SKU : List<string[]>
{
public string SKU_ID { get; set; }
public string SKU_Name { get; set; }
public string Code { get; set; }
public string Product_Name { get; set; }
public string DistributionCenter_Name { get; set; }
internal static SKU ParseRow(string row)
{
var columns = row.Split(';');
return new SKU()
{
SKU_ID = columns[0],
SKU_Name = columns[1],
Code = columns[2],
Product_Name = columns[3],
DistributionCenter_Name = columns[4],
};
}
}
In the script i named each column like in the csv file and in my database.
My main is as following
class Programm
{
static void Main(string[] args)
{
var sku_info = ProcessCSV("skutest1.csv");
SqlConnection conn = new SqlConnection();
conn.ConnectionString = #"...";
foreach (var information in sku_info)
{
using SqlConnection connection = new SqlConnection(conn.ConnectionString);
string commandString = ("INSERT INTO SKU VALUES ('" + information.SKU_ID + " "+information.SKU_Name+" "+information.Code+" "+information.Product_Name+" "+information.DistributionCenter_Name+"')");
conn.Open();
SqlTransaction transaction = conn.BeginTransaction();
SqlCommand cmd = new SqlCommand(commandString, conn, transaction);
cmd.ExecuteNonQuery();
transaction.Commit();
}
Console.ReadKey();
}
private static List<SKU> ProcessCSV(string path)
{
return File.ReadAllLines("C:/.../skutest1.csv").Where(row => row.Length > 0).Select(SKU.ParseRow).ToList();
}
}
The fastest way to load a file on the server would be to use BULK INSERT, eg :
BULK INSERT someTable
FROM 'pathtofile`
WITH ( FORMAT = 'CSV' )
You can do something similar by using ADO.NET's SqlBulkCopy class to execute a BULK INSERT operation with data sent from the client. SqlBulkCopy expects either a DataTable or IDbDataReader parameter. You can use CsvHelper' CsvDataReader for this. The CsvDataReader parses a CSV file and produces the IDbDataReader interface needed by SqlBulkCopy.
The code could be as simple as this :
using var txtReader = File.OpenText(pathToCSV);
var reader = new CsvReader(txtReader,CultureInfo.InvariantCulture);
using var dbReader = new CsvDataReader(reader);
var bcp = new SqlBulkCopy(cns);
bcp.ColumnMappings.Add("sku_id","sku_id");
bcp.ColumnMappings.Add("sku_name","sku_name");
...
bcp.DestinationTableName = table;
bcp.WriteToServer(dbReader);
Without the mappings SqlBulkCopy will send the columns in the order they appear in the file. If that doesn't match the order of the table columns, you'll get an error or worse, get mixed up data
Here's a short tutorial on building a parameterized commandstring - this is a much safer way of inserting to your database.
Here's a sample of how you could parameterize your insert:
string commandString = (#"INSERT INTO SKU VALUES (#sku_id, #sku_name, #code, #product_name, #distributioncenter_name");
conn.Open();
SqlTransaction transaction = conn.BeginTransaction();
SqlCommand cmd = new SqlCommand(commandString, conn, transaction);
cmd.Parameters.Add(new SqlParameter("#sku_id", information.SKU_ID));
cmd.Parameters.Add(new SqlParameter("#sku_name", information.SKU_Name));
cmd.Parameters.Add(new SqlParameter("#code", information.Code));
cmd.Parameters.Add(new SqlParameter("#product_name", information.Product_Name));
cmd.Parameters.Add(new SqlParameter("#distributioncenter_name", information.DistributionCenter_Name));
cmd.ExecuteNonQuery();
transaction.Commit();
I am a high school student who's still pretty much a beginner in C#.
I am making a library management system (for books) that includes a database (sql local database in visual studio(?)) for users. I have a form wherein users can view the data they have input in the registration form (userID, name, username, course, section). The only problem is that it only displays the data of the first account created. No matter how many other accounts I create, it still only ever displays the first one. How do I make it so that it shows the data of the "current" user/account logged in?
I've tried slightly changing the code by changing
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select * from [tbl_accounts]";
into
string select = "Select * from [tbl_accounts]";
SqlCommand cmd = new SqlCommand(select, conn);
Although, I think they're basically the same. I don't really know what to do since the other solutions I've found are much more complex.
This is the code that I am using right now:
try
{
SqlConnection conn = new SqlConnection(#"[connection string]");
conn.Open();
string select = "Select * from [tbl_accounts]";
SqlCommand cmd = new SqlCommand(select, conn);
SqlDataReader dr = cmd.ExecuteReader();
if(dr.Read())
{
materialLabel6.Text = dr["accountID"].ToString();
materialLabel7.Text = dr["username"].ToString();
materialLabel8.Text = dr["name"].ToString();
materialLabel9.Text = dr["strand"].ToString();
materialLabel10.Text = dr["section"].ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);}
}
The outcome that I would like to see is for example:
Users(table):
PersonA
PersonB
Currently Logged in: PersonB
[PERSONB'S DATA]
So it means that the form will only display the data of PersonB instead of PersonA's
For starters, if you need more than one row of data, you'll want to loop through all the rows in the data reader. Right now you're only getting the first row returned. This link should have the relevant information for that. However, ideally, you'd want to send a parameter from the UI (or whatever it is that you're using to fire off the call to the function) that denotes the user (an ID or any unique field in the Users table) and send that to the sql query's where clause so you only pull the record(s) that you need.
The query should probably look something like:
public void GetUserInfo(int userId) // though you might want to change the parameter to suit your needs. It's hard to tell without being able to see the schema
{
string select = string.Format("Select * from [tbl_accounts] where Id = {0}", userId.ToString()); // something along these lines
SqlCommand cmd = new SqlCommand(select, conn);
SqlDataReader dr = cmd.ExecuteReader();
if(dr.Read())
{
materialLabel6.Text = dr["accountID"].ToString();
materialLabel7.Text = dr["username"].ToString();
materialLabel8.Text = dr["name"].ToString();
materialLabel9.Text = dr["strand"].ToString();
materialLabel10.Text = dr["section"].ToString();
}
}
Edit: quick note, if you adjust your query so it pulls one record based off of a parameter, you shouldn't need to do the looping.
Another quick edit: I broke up the code so it's a little more readable. This is more of an 'ideal implementation,' and enforces some better practices for code. (I know it's a high school project, but it's best to get used to breaking up code so it's more generic early on imo. This is mostly for maintainability. On larger projects keeping everything so closely coupled together is hard to manage.)
public User GetUserInfo(int userId) // though you might want to change the parameter to suit your needs. It's hard to tell without being able to see the schema for the user table
{
SqlConnection conn = new SqlConnection(#"[connection string]");
conn.Open();
string select = string.Format("Select * from [tbl_accounts] where Id = {0}", userId.ToString()); // something along these lines
SqlCommand cmd = new SqlCommand(select, conn);
SqlDataReader dr = cmd.ExecuteReader();
User user = new User();
if(dr.Read())
{
user.AccountId = dr["accountID"].ToString();
user.UserName = dr["username"].ToString();
user.Name = dr["name"].ToString();
user.Strand = dr["strand"].ToString();
user.Section = dr["section"].ToString();
}
return user;
}
public void SetValues(User user)
{
materialLabel6.Text = user.AccountId;
materialLabel7.Text = user.UserName;
materialLabel8.Text = user.Name;
materialLabel9.Text = user.Strand;
materialLabel10.Text = user.Section;
}
public class User
{
string AccountId { get; set; }
string UserName { get; set; }
string Name { get; set; }
string Strand { get; set; }
string Section { get; set; }
}
After running a MySqlCommand and then reading a row with MySqlDataReader, is it possible to store that entire row into a single variable?
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
// Store a single row into a variable
// Pass the variable into another method
}
The best thing you can achieve is explained in the MSDN docs about the IDataRecord interface, but at the end you still need to read each single column and store them somewhere.
However a more object oriented approach is to have a class that represents the data from your record, create an instance of that class and initialize its properties, then pass the instance to another method
So suppose that the query you have used is a simple
SELECT IDPerson, FirstName, LastName from Persons
Now you have defined somewhere your class Person
public class Person
{
public int IDPerson {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
Then your loop works with
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
// Declare and initialize the instance of a Person
// (this is a single variable as per your requirements)
Person p = new Person()
{
IDPerson = rdr.GetInt32(0),
FirstName = rdr.GetString(1),
LastName = rdr.GetString(2)
};
ProcessPerson(p);
}
So I have code that stores an UPDATE query in a string, then I parameter bind the update query and then execute and update it, this is my code:
string query = "UPDATE Users SET first_name = '#firstname' WHERE ID = #id";
updateUserDS.UpdateParameters.Add("id", HTTPContext.Current.Session["ColumnID"].ToString());
updateUserDS.UpdateParameters.Add("firstname", txt_firstname.Text);
updateUserDS.UpdateCommand = query;
updateUserDS.Update();
However when I change my string query to:
string query = "UPDATE Users SET first_name = 'name' WHERE ID = 44";
It works perfectly and updates my table, so I am guessing its something to do with how I have binded the query, does anyone realise anything where I have gone wrong?
BTW: The Session["ColumnID"] is being retrieved perfectly as it states 44 in the stack trace
Remove the single quotes from #firstname:
string query = "UPDATE Users SET first_name = #firstname WHERE ID = #id";
updateUserDS.Parameters.AddWithValue("#firstname", first_name);
updateUserDS.Parameters.AddWithValue("#id", HTTPContext.Current.Session["ColumnID"].ToString());
EDIT:
Assuming you are using SQL Server as database try like this:
SqlCommand sqlComm = new SqlCommand();
sqlComm.CommandText = #"UPDATE Users SET first_name = #firstname WHERE ID = #id";
sqlComm.Parameters.Add("#firstname", SqlDbType.VarChar);
sqlComm.Parameters["#firstname"].Value = txt_firstname.Text;
sqlComm.Parameters.Add("#id", SqlDbType.VarChar);
sqlComm.Parameters["#id"].Value = HTTPContext.Current.Session["ColumnID"].ToString();
using (SqlConnection sqlConn = new SqlConnection(connection string here);)
{
sqlComm.Connection = sqlConn;
sqlConn.Open();
sqlComm.ExecuteNonQuery();
}
I'd rewrite this as to use OldDbCommand and OleDbConnection instead of SqlDataSource. It doesn't depend on System.Web assembly (smaller deployment size for non-web situations), there's fewer layers in the stack trace (faster), and it's how most people are used to using ADO.NET.
var command = new OleDbCommand("UPDATE Users SET first_name = ? WHERE ID = ?");
command.Parameters.AddWithValue("id", Session["ColumnID"].ToString());
command.Parameters.AddWithValue("firstname", txt_firstname.Text);
using (var connection = new OleDbConnection(connectionString))
{
command.Connection = connection;
connection.Open();
command.ExecuteNonQuery();
}
Another note, you seem to be doing your database access directly in the UI layer! That's hard to test, and not very flexible. It'd be better if you moved all data access code into a separate class library, and then communicate back and forth by passing Models, which are code representations of database entities.
You're also using Access, which isn't really that great of a database system. MS SQL Server is much preferable.
That might look something like this:
Code Behind
DataLayer DB {get; set;}
protected void Page_Load(object sender, EventArgs e)
{
DB = new DataLayer("connectionstring");
}
protected void SubmitBtn_Click(object sender, EventArgs e)
{
SystemUser user = new SystemUser()
{
Id = Session["ColumnID"].ToString(),
FirstName = txt_firstname.Text
}
DB.UpdateUser(user);
}
Data Layer
public class DataLayer
{
string ConnectionString {get; set;}
public DataLayer(string connectionString)
{
ConnectionString = connectionString;
}
public void UpdateUser(SystemUser user)
{
var command = new SqlCommand("UPDATE Users SET first_name = #firstname WHERE ID = #id");
command.Parameters.AddWithValue("id", user.Id);
command.Parameters.AddWithValue("firstname", user.FirstName);
using (var connection = new SqlConnection(ConnectionString))
{
command.Connection = connection;
connection.Open();
command.ExecuteNonQuery();
}
}
public void ChangePassword(string UserId, string password)
{
//hash and change password here
}
}
Models
public class SystemUser
{
public string Id {get; set;}
public string FirstName {get; set;}
}