multiple SQL commands. Good style? - asp.net

I got an asp.net application running perfectly fine. in my code i have the following lines
using (SqlConnection con = new SqlConnection(CS))
{
SqlCommand getGenreId = new SqlCommand("Select ID from tblGenre WHERE Genre=#newGenre;", con);
getGenreId.Parameters.AddWithValue(#"newGenre", newGenre);
SqlCommand cmd = new SqlCommand("UPDATE tblSong SET Title=#newTitle, ArtistId=#newArtistId, GenreId=#newGenreId WHERE (ID = #songId);", con);
cmd.Parameters.AddWithValue(#"newTitle", newTitle);
cmd.Parameters.AddWithValue(#"newArtistId", newArtistId);
cmd.Parameters.AddWithValue(#"songId", songId);
con.Open();
newGenreId = (int)getGenreId.ExecuteScalar();
cmd.Parameters.AddWithValue(#"newGenreId", newGenreId);
cmd.ExecuteNonQuery();
}
i know database connections are valuable resources and i should be careful when using them. (open as late as possible and make sure they will be closed aswell)
My question now is this code considered bad style because im opening the connection then have as sql query to get an ID and then have another sql query to insert a record.
thanks you!

If you convert to using stored procedure, you can eliminate 1 round trip, therefore reducing network traffic and possibly increase performance.
using (SqlCommand cmd = new SqlCommand("Update_tblSong", con);
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#newGenre", newGenre);
cmd.Parameters.AddWithValue("#newTitle", newTitle);
cmd.Parameters.AddWithValue("#newArtistId", newArtistId);
cmd.Parameters.AddWithValue("#songId", songId);
cmd.ExecuteNonQuery();
}
Proc will be like this, I estimated on your variable size.
CREATE PROC Update_tblSong
(
#newGenre VARCHAR(25)
,#newTitle VARCHAR(50)
,#newArtistID INT
,#songID INT
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #NewGenreID INT;
SELECT #NewGenreID = ID
FROM tblGenre
WHERE Genre = #newGenre;
UPDATE tblSong
SET Title = #newTitle
,ArtistId = #newArtistId
,GenreId = #NewGenreID
WHERE ( ID = #songId )
END;

Overall your code flow seems fine, you are using a single connection to execute multiple (related) commands.
You can improve it further with enclosing your command objects in using statement. Since they implement IDisposable interface, just like your connection object.
using (SqlConnection con = new SqlConnection(CS))
{
con.Open();
using (SqlCommand getGenreId = new SqlCommand("Select ID from tblGenre WHERE Genre=#newGenre;", con))
{
getGenreId.Parameters.AddWithValue(#"newGenre", newGenre);
newGenreId = (int)getGenreId.ExecuteScalar();
}
using (SqlCommand cmd = new SqlCommand("UPDATE tblSong SET Title=#newTitle, ArtistId=#newArtistId, GenreId=#newGenreId WHERE (ID = #songId);", con))
{
cmd.Parameters.AddWithValue(#"newTitle", newTitle);
cmd.Parameters.AddWithValue(#"newArtistId", newArtistId);
cmd.Parameters.AddWithValue(#"songId", songId);
cmd.Parameters.AddWithValue(#"newGenreId", newGenreId);
cmd.ExecuteNonQuery();
}
}

Why not use a single query with a subquery for your SQL?
UPDATE tblSong SET Title = #newTitle, ArtistId = #newArtistId, GenreId = (Select top 1 ID from tblGenre WHERE Genre=#newGenre ORDER BY Genre) WHERE (ID = #songId);

Related

Run sp_msforeachdb to select dbsize used in c#

I have a query as such:
EXEC sp_msforeachdb
'USE [?];
SELECT DB_NAME() AS [Database Name],
CAST(SUM(FILEPROPERTY(name, ''SpaceUsed''))/128.0 AS decimal(18,2)) AS [Used space(MB)]
FROM sys.database_files
Where type_desc = ''ROWS'' and
GROUP BY type_desc'
and executing this in MSSM is alright.
My problem is that I need to execute this in my application using c# and stored in a Datatable. Any idea how to do this?
Tried looking for at CommandType.StoredProcedure and CommandType.Textbut still can't figure it out.
FYI, I'm not allowed to create a new stored procedure for this.
EDIT (SAMPLE CODE)
using (SqlConnection sqlConnection = new SqlConnection(HoustonSqlCon))
{
const string query = "EXEC sp_msforeachdb 'USE [?]; SELECT DB_NAME() AS[Database Name]," +
"CAST(SUM(FILEPROPERTY(name, ''SpaceUsed'')) / 128.0 AS decimal(18, 2)) AS[Used space(MB)]" +
"FROM sys.database_files" +
"Where type_desc = ''ROWS''" +
"GROUP BY type_desc'";
using (SqlCommand comm = new SqlCommand(query, sqlConnection))
{
sqlConnection.Open();
comm.CommandType = CommandType.Text;
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.Fill(totalSchemas);
}
}

My SqlDatareader was not working

I have a code for fetching customer_id and I use a SqlDataReader for reading customer_id from SQL Server. I test witch using breakpoint and step by step debugging and I understand the SqlDataReader condition was not compile and compiler jump straight in to the connection.close line:
string strQuery = "select customer_id from Registration where username=#username and password=#password";
SqlConnection connection1 = DBConnection.getConnection();
connection1.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection1;
cmd.CommandText = strQuery;
cmd.Parameters.AddWithValue("username", txt1_username.Text);
cmd.Parameters.AddWithValue("password", txt2_password.Text);
string customer_id = cmd.ExecuteScalar() as string;
connection1.Close();
if (customer_id == null)
{
Messages myMsg = new Messages();
myMsg.CreateMessageAlert("The User does not Registered or your using incorect username or password");
}
else {
Session["customer_id"] = customer_id;
}
Although the issue is not very clear, you can try to revise the code taking following into account:
There is no need to open/close db connection for every sql query in a method. Open it once, execute all queries, close. That will make code clear and faster.
As you take connection from somewhere else, make sure it is closed before you open it (Example: Check if SQL Connection is Open or Closed)
You run 2 queries and in both cases you get only 1 result (select count(*), select customer_id). Why then in first case you do ExecuteScalar() and ExecuteReader() in the other?
The other thought is there is no need to have 2 SqlCommand(), etc if you need to return results of 2 queries. Read about Retrieving Multiple Result Sets using NextResult
And last but not least - it seems you need to check if user is already registered and if true, get his id. Why not do it in one shot? The second query is good for both cases - if user does not exist, query will not return any result, if he does - his id will be returned. Doing this way, you would need only one query and less coding.
UPDATE:
The updated code looks more clear and straightforward, but you didn't get the point of my last comment. If you select count(customer_id) you get a count that you don't need. Why not simply select customer_id and check if it was returned or not?
Example:
//string strQuery = "select count(customer_id) from Registration where username=#username and password=#password";
string strQuery = "select customer_id from Registration where username=#username and password=#password";
SqlConnection connection1 = DBConnection.getConnection();
connection1.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection1;
cmd.CommandText = strQuery;
cmd.Parameters.AddWithValue("username", txt1_username.Text);
cmd.Parameters.AddWithValue("password", txt2_password.Text);
//int intRowCount = (int)cmd.ExecuteScalar();
string customer_id = cmd.ExecuteScalar() as string;
//txt1_username.Text = intRowCount.ToString(); <-- What's this?
connection1.Close();
//if (intRowCount == 1)
if (customer_id == null)
{
// user does not exist, because sql returned no rows
... <-- do something here
} else {
Session["customer_id"] = customer_id;
}
UPDATE #2:
To troubleshoot
Make sure txt1_username.Text and txt2_password.Text have expected values. It could be that you reset the Text somewhere and that could be the reason why the query returned no result. Try to hardcode the value in the code, for example,
cmd2.Parameters.AddWithValue("username", "admin");
cmd2.Parameters.AddWithValue("password", "123");
Copy-paste entire sql in Sql Server Management Studio (or other tool) and run it from here to ensure what result it returned.
Make sure you execute it against correct database (maybe you have different databases with same tables where data is different).
This is because your username is no longer the username. It is actually 1 because of the line
int intRowCount = (int) cmd.ExecuteScalar();
txt1_username.Text = intRowCount.ToString(); <-- RED FLAG
So in the inside the If, you are actually running
SELECT customer_id FROM registration WHERE username=1 and password=my_password
Comment line 15 and you should do fine.
updated
string strQuery = "select count(*) from Employee where FullName=#username";
SqlConnection connection = DBConnection.getConnection();
connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = strQuery;
cmd.Parameters.AddWithValue("username", txt1_username.Text);
cmd.Parameters.AddWithValue("password", txt2_password.Text);
int intRowCount = (int)cmd.ExecuteScalar();
txt1_username.Text = intRowCount.ToString();
if (intRowCount == 1)
{
string strquery = "select customer_id from Registration where username=#username and password=#password";
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = connection;
cmd2.CommandText = strquery;
cmd2.Parameters.AddWithValue("username", txt1_username.Text);
cmd2.Parameters.AddWithValue("password", txt2_password.Text);
SqlDataReader reader = cmd2.ExecuteReader();
if (reader.Read())
{
string customerID = reader[0].ToString();
}
}
connection.Close();`
This is complete solution for your issue.
Do not need to open connection everytime. just make sure, connection is being closed once it's used.

asp.net insert data into DB

con.Open();
cmd2 = new SqlCommand("insert into dailyWorkout('"+RadioButton1.Text+"', '"+RadioButton2.Text+"', '"+RadioButton3.Text+"', '"+RadioButton4.Text+"', '"+RadioButton5.Text+"', '"+Label1.Text+"')", con);
cmd2.ExecuteNonQuery();
Hey guys, been working on this website for a while, but I get an error when putting data into the database saying
Incorrect syntax near ')'.
With other stuff that I'm putting same way it works and this does not.
You should really really REALLY use parametrized queries to avoid SQL injection (and to boost performance; and avoid issues with type conversions etc.)
So I would recommend using code something like this:
// define your *parametrized* SQL statement
string insertStmt = "INSERT INTO dbo.YourTable(Col1, Col2, Col3) VALUES(#Val1, #Val2, #Val3);";
// put SqlConnection and SqlCommand into "using" blocks to ensure proper disposal
using(SqlConnection conn = new SqlConnection("-your-connection-string-here-"))
using(SqlCommand cmd = new SqlCommand(insertStmt, conn))
{
// set the parameters to the values you need
cmd.Parameters.AddWithValue("#Val1", "Some String here");
cmd.Parameters.AddWithValue("#Val2", 42);
cmd.Parameters.AddWithValue("#Val3", DateTime.Today.AddDays(-7));
// open connection, execute query, close connection right away
conn.Open();
int rowsAffected = cmd.ExecuteNonQuery();
conn.Close();
}
Points to remember:
ALWAYS use parametrized queries - do NOT concatenate together your SQL statements!
put the SqlConnection and SqlCommand into using(...) { ... } blocks to ensure proper disposal
always explicitly define the list of columns you want to use in a SELECT and also an INSERT statement
open connection as late as possible, execute query, close connection again right away
That will do the job but I strongly advice using Parameters.
con.Open();
cmd2 = new SqlCommand("insert into dailyWorkout values ('"+RadioButton1.Text+"', '"+RadioButton2.Text+"', '"+RadioButton3.Text+"', '"+RadioButton4.Text+"', '"+RadioButton5.Text+"', '"+Label1.Text+"')", con);
cmd2.ExecuteNonQuery();
Instead of the code above you'd better to use
cmd2 = new SqlCommand("insert into dailyWorkout values (#val1, #val2, #val3,#val4,#val5,#val6)", con);
cmd2.Parameters.AddWithValue("#val1",RadioButton1.Text);
cmd2.Parameters.AddWithValue("#val2",RadioButton2.Text);
cmd2.Parameters.AddWithValue("#val3",RadioButton3.Text);
cmd2.Parameters.AddWithValue("#val4",RadioButton4.Text);
cmd2.Parameters.AddWithValue("#val5",RadioButton5.Text);
cmd2.Parameters.AddWithValue("#val6",Label1.Text)
cmd2.ExecuteNonQuery();
Ok its already been mentioned, don't inject parameters like that.
But if you must, the problem is that your final sql string looks like:
insert into dailyWorkout('string1', 'string2', 'string3', 'string4', 'string5', 'string6')
when it should be
insert into dailyWorkout(columnName1,columnName2,columnName3,columnName4,columnName5,columnName6)
values('string1', 'string2', 'string3', 'string4', 'string5', 'string6')
But you should really consider:
var sqlCmd = new SqlCommand("insert into dailyWorkout(columnName1,columnName2,columnName3,columnName4,columnName5,columnName6) values(#v1, #v2, #v3, #v4, #v5, #v6)", default(SqlConnection));
sqlCmd.Parameters.Add("#v1", SqlDbType.NVarChar).Value = RadioButton1.Text;
sqlCmd.Parameters.Add("#v2", SqlDbType.NVarChar).Value = RadioButton2.Text;
sqlCmd.Parameters.Add("#v3", SqlDbType.NVarChar).Value = RadioButton3.Text;
sqlCmd.Parameters.Add("#v4", SqlDbType.NVarChar).Value = RadioButton4.Text;
sqlCmd.Parameters.Add("#v5", SqlDbType.NVarChar).Value = RadioButton5.Text;
sqlCmd.Parameters.Add("#v6", SqlDbType.NVarChar).Value = Label1.Text;
sqlCmd.ExecuteNonQuery();

Oracle query/ stored procedure to return multiple resultsets

I am using oracle database. When I tried to fetch the data using a single select query, it returned a single table in the dataset.
How to write a select query or procedure in oracle, where I can get a dataset with 2-3(multiple) tables?
As far as I understood you question you would like to reduce the round trips to your database.
This can be done by a stored procedure in the following way:
http://msdn.microsoft.com/en-us/library/ms971506.aspx#msdnorsps_topic6
Package header:
CREATE OR REPLACE PACKAGE SELECT_JOB_HISTORY AS
TYPE T_CURSOR IS REF CURSOR;
PROCEDURE GetJobHistoryByEmployeeId
(
p_employee_id IN NUMBER,
cur_JobHistory OUT T_CURSOR
);
END SELECT_JOB_HISTORY;
Package:
CREATE OR REPLACE PACKAGE BODY SELECT_JOB_HISTORY AS
PROCEDURE GetJobHistoryByEmployeeId
(
p_employee_id IN NUMBER,
cur_JobHistory OUT T_CURSOR
)
IS
BEGIN
OPEN cur_JobHistory FOR
SELECT * FROM JOB_HISTORY
WHERE employee_id = p_employee_id;
END GetJobHistoryByEmployeeId;
END SELECT_JOB_HISTORY;
Client:
// create connection
OracleConnection conn = new OracleConnection("Data Source=oracledb;
User Id=UserID;Password=Password;");
// create the command for the stored procedure
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId";
cmd.CommandType = CommandType.StoredProcedure;
// add the parameters for the stored procedure including the REF CURSOR
// to retrieve the result set
cmd.Parameters.Add("p_employee_id", OracleType.Number).Value = 101;
cmd.Parameters.Add("cur_JobHistory", OracleType.Cursor).Direction =
ParameterDirection.Output;
// open the connection and create the DataReader
conn.Open();
OracleDataReader dr = cmd.ExecuteReader();
// output the results and close the connection.
while(dr.Read())
{
for(int i = 0; i < dr.FieldCount; i++)
Console.Write(dr[i].ToString() + ";");
Console.WriteLine();
}
conn.Close();
If you have to join these tables you can also use a normal join and split the result on the client (imho this is the way how a lot of ORMs do it).
This is exactly what I did, it was quite simple :
Database db = DatabaseFactory.CreateDatabase("ConnectionString");
object[] results = new object[3];
DbCommand cmd = db.GetStoredProcCommand("DATABASE.SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId",results);
DataSet ds = db.ExecuteDataSet(cmd);
DataTable dt1 = ds.Tables[0];
DataTable dt2 = ds.Tables[1];

how to run two queries using the code snippet below?

How to Run two Update Sql Queries using this Sql Snippet ?
The code mentioned below is updating values only in one table .... i want to update data in two different tables using the code mentioned below :
can anybody reedit this code ?
Try
Using conn = New SqlConnection(constr)
Using cmd = conn.CreateCommand()
conn.Open()
Dim sql As String =
"UPDATE a1_ticket
SET Ticket_no =#ticketNo,
BANK = #bank,
PAID = #paid,
BID = #bid
WHERE ITC = #ticketNo"
cmd.CommandText = sql
cmd.Parameters.AddWithValue("#bank", Literal20.Text)
cmd.Parameters.AddWithValue("#paid", Label1.Text)
cmd.Parameters.AddWithValue("#bid", Literal21.Text)
cmd.Parameters.AddWithValue("#ticketNo", Literal3.Text)
cmd.ExecuteNonQuery()
End Using
End Using
Catch ex As Exception
Response.Write(ex.Message)
End Try
Create a Stored Procedure that updates the two tables and execute it using a StoredProcedure Command...
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "UpdateTheTwoTables";
....
Modify the SQL statement to update the two tables.
Using a Stored Procedure is the cleanest way code wise. If you don't feel comfortable doing it like that, I'm sure you can do it like this:
Try
Using conn = New SqlConnection(constr)
Using cmd = conn.CreateCommand()
conn.Open()
Dim sql As String = "UPDATE a1_ticket SET Ticket_no =#ticketNo, BANK = #bank, PAID = #paid, BID = #bid WHERE ITC = #ticketNo"
cmd.CommandText = sql
cmd.Parameters.AddWithValue("#bank", Literal20.Text)
cmd.Parameters.AddWithValue("#paid", Label1.Text)
cmd.Parameters.AddWithValue("#bid", Literal21.Text)
cmd.Parameters.AddWithValue("#ticketNo", Literal3.Text)
cmd.ExecuteNonQuery()
End Using
//
Using cmd = conn.CreateCommand()
conn.Open()
Dim sql As String = "UPDATE a2_ticket SET Ticket_no =#ticketNo, BANK = #bank, PAID = #paid, BID = #bid WHERE ITC = #ticketNo"
cmd.CommandText = sql
cmd.Parameters.AddWithValue("#bank", Literal20.Text)
cmd.Parameters.AddWithValue("#paid", Label1.Text)
cmd.Parameters.AddWithValue("#bid", Literal21.Text)
cmd.Parameters.AddWithValue("#ticketNo", Literal3.Text)
cmd.ExecuteNonQuery()
End Using
End Using
Catch ex As Exception
Response.Write(ex.Message)
End Try
It's a sketch of what I'm trying to say, you may want to change a few things here and there, but the point is you can just update your two tables one after the other. It's not possible in one update statement afaik.
you can also use
Dim sql As String = # "Query for first update;
Query for second update;";
Well as you havent said anything about the second table, or the data you're sending it. I havent put this through the compiler to verify it, but the concept I'd suggest would be
You could do:
void UpdateDB(String sql, String[][] params)
{
Try
{
SqlConnection conn = New SqlConnection(constr);
SqlCommand cmd = conn.CreateCommand();
conn.Open();
cmd.CommandText = sql;
for(int i=0; i<params.length; i++)
{
cmd.Parameters.AddWithValue(params[i,0] params[i,1]);
}
cmd.ExecuteNonQuery();
}
Catch (Exception ex)
{
Response.Write(ex.Message);
}
}
eg send the SQL and the parameters to the function and have it do all the work..

Resources