How to make a parameterized SELECT query in C#? - c#

I'm trying to display data from a table in database using DataGridView and a parameterized query in C# and SQL Server.
So far, I have tried this code:
private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=.\SQLEXPRESS01;Initial Catalog=Vagtplan;Integrated Security=True");
SqlCommand cmd = new SqlCommand("SELECT Ansatte.ansatID = #ansat, Ansatte.Navn = #navn, Ansatte.Efternavn = #efternavn, Ansatte.Adresse = #adresse, Ansatte.Postnummer = #postnummer, Ansatte.Bynavn = #bynavn, Ansatte.Email = #email, Ansatte.Mobilnr = #mobilnr, Login_data.Brugertype = #brugertype FROM Ansatte INNER JOIN Login_data ON Ansatte.ansatID = Login_data.ansatID", con);
cmd.Parameters.Add("#ansat", SqlDbType.Int);
cmd.Parameters.Add("#navn", SqlDbType.VarChar);
cmd.Parameters.Add("#eftervavn", SqlDbType.VarChar);
cmd.Parameters.Add("#adresse", SqlDbType.VarChar);
cmd.Parameters.Add("#postnummer", SqlDbType.Int);
cmd.Parameters.Add("#bynavn", SqlDbType.VarChar);
cmd.Parameters.Add("#email", SqlDbType.VarChar);
cmd.Parameters.Add("#mobilnr", SqlDbType.Int);
cmd.Parameters.Add("#brugertype", SqlDbType.VarChar);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
dataGridView2.DataSource = dt;
}
But I get the following error:
Incorrect syntax near '='
How to fix it so I can select data using a parameterized query? Expected result is, that data will be displayed in a DataGridView.

You have a few things going on here, and I'll try to break down for you. Working with a database, you typically do a "select...from..." to get data and "insert into..." to add records to the tables.
Next, your query. A shortened version of yours.. The problem here is you are trying to assign the #ansat PARAMETER value INTO the Ansatte.ansatID field which is incorrect syntax context to begin with, but review on regardless.
SqlCommand cmd = new SqlCommand(
#"SELECT
Ansatte.ansatID = #ansat,
Ansatte.Navn = #navn,
Ansatte.Efternavn = #efternavn,
Ansatte.Adresse = #adresse...
FROM
Ansatte
INNER JOIN Login_data
ON Ansatte.ansatID = Login_data.ansatID", con);
and then adding the parameters...
cmd.Parameters.Add("#ansat", SqlDbType.Int);
cmd.Parameters.Add("#navn", SqlDbType.VarChar);
cmd.Parameters.Add("#eftervavn", SqlDbType.VarChar);
cmd.Parameters.Add("#adresse", SqlDbType.VarChar);
Good you are using parameters, but you just DECLARED the parameters, you never assigned any actual values to them, which in essence is resulting in the following getting passed to the engine
SELECT
Ansatte.ansatID = ,
Ansatte.Navn = ,
Ansatte.Efternavn = ,
Ansatte.Adresse =
FROM
Ansatte
INNER JOIN Login_data
ON Ansatte.ansatID = Login_data.ansatID
Hence probably your error for no value for the = sign. Now, to actually add the "Value" to your parameter... Your declaration appeared ok, just finish it with a value that could be a fixed value, from a window entry, config setting, whatever...
cmd.Parameters.Add("#ansat", SqlDbType.Int).Value = 123;
cmd.Parameters.Add("#navn", SqlDbType.VarChar).Value = "test";
cmd.Parameters.Add("#eftervavn", SqlDbType.VarChar).Value = "more";
cmd.Parameters.Add("#adresse", SqlDbType.VarChar).Value = "done";
which would result in a protected (non-sql-injection)
Now, what you might really be looking for. You have a table in your database that you want to pull information from. In this case, select the columns you WANT, not the values you want to SET. Just query. Ex:
SqlCommand cmd = new SqlCommand(
#"SELECT
Ansatte.ansatID,
Ansatte.Navn,
Ansatte.Efternavn,
Ansatte.Adresse,
Ansatte.Postnummer,
Ansatte.Bynavn,
Ansatte.Email,
Ansatte.Mobilnr,
Login_data.Brugertype
FROM
Ansatte
INNER JOIN Login_data
ON Ansatte.ansatID = Login_data.ansatID", con);
If you run the above query, it will return all records that are in the database that have a matching ID between each respective table.
Now, tack on parameters to a SQL-SELECT query. Say you only wanted all names within a given PostNumber area. Add a WHERE condition for such field and parameterized value such as
FROM
Ansatte
INNER JOIN Login_data
ON Ansatte.ansatID = Login_data.ansatID
where
Ansatte.Postnummer = #MyPostCriteria", con );
cmd.Parameters.Add("MyPostCriteria", SqlDbType.Int).Value = 11223;
Now, if you are trying to ADD a record TO the database, that would be an insert, and you can only do an insert into a single table at a time and might be something like below. You identify the table and columns you want to insert, and then the values in the same sequence as their corresponding sequence as added in parenthesis list at the top.. Then parameterize
SqlCommand cmd = new SqlCommand(
#"INSERT INTO Ansatte
( Navn,
Efternavn,
Adresse
)
values
( #parmForNavn,
#parmForEfternavn,
#parmForAdresse
)", con);
cmd.Parameters.Add("parmForNavn", SqlDbType.VarChar).Value = "test";
cmd.Parameters.Add("parmForEfternavn", SqlDbType.VarChar).Value = "blah";
cmd.Parameters.Add("parmForAdresse", SqlDbType.VarChar).Value = "123 some street";
Hopefully this can jump-start you into what you are trying to accomplish from either pulling data down from a database, or insert into.

Related

How to fix "System.Data.SqlClient.SqlException: 'Column name or number of supplied values does not match table definition.'" in asp.net

I'm trying to connect my SQL Server with ASP.NET, and when I run my insert function, it displays an error.
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Insert into Table1 values('"+firstname.Text+"','"+lastname.Text+"','"+city.Text+"')";
cmd.ExecuteNonQuery();
firstname.Text = "";
lastname.Text = "";
city.Text = "";
I expect to show the inserted values but it displays this error:
System.Data.SqlClient.SqlException: 'Column name or number of supplied values does not match table definition.'
Where Id is auto incremented.
You need urgently research about SQL injection, and STOP USING string concatenation for building your SQL insert statement RIGHT NOW.
You need to use the proper technique - parametrized queries -- always - NO exceptions!
And also, it's a commonly accepted Best Practice to list the columns in your INSERT statement, to avoid trouble when tables change their columns (read more about this here: Bad habits to kick: using SELECT * / omit the column list ).
Use this code as a sample/template:
string insertQuery = #"INSERT INTO dbo.Table1 (FirstName, LastName, City)
VALUES (#FirstName, #LastName, #City);";
using (SqlCommand cmd = new SqlCommmand(insertQuery, con))
{
cmd.Parameters.Add("#FirstName", SqlDbType.VarChar, 50).Value = firstname.Text;
cmd.Parameters.Add("#LastName", SqlDbType.VarChar, 50).Value = lastname.Text;
cmd.Parameters.Add("#City", SqlDbType.VarChar, 50).Value = city.Text;
con.Open();
cmd.ExecuteNonQuery();
con.Close()
}
You should specify the columns names. For example:
cmd.CommandText = $"Insert into Table1 ({ColumnName of firstname}, { ColumnName of lastname}, { ColumnName of city})
values({firstname.Text}, {lastname.Text}, {city.Text})";
You can better use a stored procedure - something like that:
cmd.CommandText = "your SP name";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#FirstName", SqlDbType.VarChar).Value = firstName.Text;
cmd.Parameters.Add("#LastName", SqlDbType.VarChar).Value = lastName.Text;
etc...

Call a SQL stored procedure in ASP.NET with an output parameter

I'm attempting to call my sql stored procedure which takes RaceDate as an input and returns Location as an OUTPUT. I'm not sure how to call my code in ASP.NET, this is what I have thus far.
DateTime RaceDate = Calendar1.SelectedDate;
// string RaceDate = TxtBoxCalendar.Text;
TxtBoxCalendar.ReadOnly = true;
SqlConnection con = new SqlConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ToString();
con.Open();
SqlCommand Command = new SqlCommand();
Command.CommandType = System.Data.CommandType.StoredProcedure;
Command.CommandText = "CheckRaceCalendarDates";
Command.Parameters.Add("#RaceDate", SqlDbType.DateTime, RaceDate);
Command.Parameters.Add("#Location", SqlDbType.String).Direction = ParameterDirection.Output;
Command.Parameters.Add("#Location",SqlDbType.String).Direction = ParameterDirection.Output;
Command.ExecuteNonQuery();
con.Close();
I think i may also run into a problem with datatypes. RaceDate is a date the user clicks through a calendar and has to be converted to a string however the SQL parameter RaceDate is of type date.
CREATE PROCEDURE [dbo].[CheckRaceCalendarDates]
#RaceDates DATE,
#Location NVARCHAR(50) OUTPUT
AS
IF EXISTS
(
SELECT
RaceCalendar.RaceDates,
Locations.LocationName
FROM
Locations
INNER JOIN RaceCalendar ON locations.LocationId = RaceCalendar.LocationId
WHERE
RaceCalendar.RaceDates = #RaceDates
)
BEGIN
SELECT
#Location = Locations.LocationName
FROM
Locations
INNER JOIN RaceCalendar ON locations.LocationId = RaceCalendar.LocationId
WHERE
RaceCalendar.RaceDates = #RaceDates
END
Your problem about using parameter name ; you have used #RaceDates on stored procedure but you try to use #RaceDate on code.. They should be same.
Also, you need to add second parameter to your code like this ;
Command.Parameters.Add("#Location",SqlDbType.String).Direction = ParameterDirection.Output;
And after cmd.ExeCuteNonQuery();
string location = Command.Parameters["#Location"].Value.ToString();

Trying to update db - no errors but no update either

I have a problem in trying to update a database using SQL update command and DataGridView.
Int16 ID, An;
// update db using sql command, the code does not update the database
SqlCommand cmd = new SqlCommand("update filme set ID = #ID, Nume = #Nume, Gen = #Gen, Descriere = #Descriere, Actori = #Actori, An = #An, Rating = #Rating, Pret = #Pret where ID = #ID");
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
cmd.Parameters.AddWithValue("#ID", SqlDbType.SmallInt).Value = Int16.TryParse("#ID", out ID);
cmd.Parameters.AddWithValue("#Nume", SqlDbType.NVarChar).Value = "#Nume";
cmd.Parameters.AddWithValue("#Gen",SqlDbType.NVarChar).Value = "#Gen";
cmd.Parameters.AddWithValue("#Descriere", SqlDbType.NVarChar).Value = "#Descriere";
cmd.Parameters.AddWithValue("#Actori", SqlDbType.NVarChar).Value = "#Actori";
cmd.Parameters.AddWithValue("#An", SqlDbType.SmallInt).Value = Int16.TryParse("#An", out An) ;
cmd.Parameters.AddWithValue("#Rating", SqlDbType.NVarChar).Value = "#Rating";
cmd.Parameters.AddWithValue("#Pret",SqlDbType.Money).Value = "#Pret";
connection.Open();
cmd.ExecuteNonQuery();
This code does not produce any errors, but does not update the database. Something is wrong but I don't know what.
I use Visual Studio Community and SQL Server 2012. The information from database are displayed in a DataGridView.
Thank you !
You set the #ID parameter with this line
Int16.TryParse("#ID", out ID);
what do you expect to be the result of converting the string #ID to an integer?
And Int16.TryParse returns a boolean, true if the conversion succeed, false otherwise.
Then you use
cmd.Parameters.AddWithValue("#ID", SqlDbType.SmallInt).Value = .....
The second parameter of AddWithValue is the Value to give to the parameter, not the type.
The remainder follows the same pattern and so this code will never work.
As an example, you should write:
SqlCommand cmd = new SqlCommand(#"update filme set Nume = #Nume, Gen = #Gen,
Descriere = #Descriere, Actori = #Actori,
An = #An, Rating = #Rating, Pret = #Pret
where ID = #ID", connection);
cmd.Parameters.Add(new SqlParameter
{ ParameterName = #Nume,
SqlDbType = SqlDbType.Int,
Value = Convert.ToInt32(someTextBox.Text) // Or some datagridview cell...
};
...and so on for the other parameters...
Notice also that I have removed the part about SET ID = #ID because this makes no sense. If you use the ID field as your search condition then updating it with the value that you are searching for could only lead, in the best situation, at no change for the ID field and in the worst situation to changing a different record from the intended one.
The way you use the .AddWithValue is all wrong .....
You have
cmd.Parameters.AddWithValue("#ID", SqlDbType.SmallInt).Value = Int16.TryParse("#ID", out ID);
but you're really defining the parameter name and datatype (which is a good thing!) and then you use the .Value = ... to handle the value assignment.
These lines of code should really be:
cmd.Parameters.Add("#ID", SqlDbType.SmallInt).Value = Int16.TryParse("#ID", out ID);
I bet using this approach, your code will work just fine.

Having some trouble using scope identity

I have two tables, one containing names, and one containing rates and other data that is lined to each name. After I insert a new name into table A, I want to get the newly auto generated PK to now use to insert into my other table B with rates.
How can I do this? I read about scope_identity online but I'm not sure how to use it.
This is what I have so far:
SqlConnection con = new SqlConnection(pubvar.x);
SqlCommand command = con.CreateCommand();
command.CommandText ="Insert into A values('" +Name + "')";
SqlCommand command2 = con.CreateCommand();
command2.CommandText = "Insert into B values(....)";
SELECT SCOPE_IDENTITY();
con.Open();
command.ExecuteNonQuery();
con.Close();
Considering the case you've described, I don't see any need to return the identity from the database. You can simply issue both statements in one command:
using (var cnx = new SqlConnection(pubvar.x))
using (var cmd = new SqlCommand
{
Connection = cnx,
CommandText = #"
insert into A (Name) values (#name)
insert into B (A_ID, Rate) values (scope_identity(), #rate)
",
Parameters =
{
new SqlParameter("#name", name),
new SqlParameter("#rate", .5m) //sample rate
}
})
{
cnx.Open();
cmd.ExecuteNonQuery();
}

System.ArgumentException: The table type parameter must have a valid type name

I am trying to pass in a user defined table type into a query in C#.
the type is defined with 2 columns (org and sub org)
this is what my code looks like:
DataSet ds = new DataSet();
try
{
DataTable FilteredOrgSubOrg = new DataTable("OrgSubOrgValueType");
FilteredOrgSubOrg.Columns.Add("org", typeof(string));
FilteredOrgSubOrg.Columns.Add("subOrg", typeof(string));
FilteredOrgSubOrg.Rows.Add(org, orgsub);
using (SqlConnection conn = new SqlConnection(cCon.getConn()))
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText =
"select * from myTable ex where year = #year' and qtr = #qtr" +
" and EXISTS(SELECT 1 FROM #OrgSubOrg tt WHERE ex.org like tt.org" +
" AND ex.orgsub = tt.suborg )"+
" order by ex.org,year, qtr DESC";
// 2. set the command object so it knows
// to execute a stored procedure
// 3. add parameter to command, which
// will be passed to the stored procedure
cmd.Parameters.Add(new SqlParameter("#OrgSubOrg", FilteredOrgSubOrg));
cmd.Parameters.Add(new SqlParameter("#year", year));
cmd.Parameters.Add(new SqlParameter("#qtr", qtr));
conn.Open();
SqlDataAdapter sqlDA = new SqlDataAdapter();
sqlDA.SelectCommand = cmd;
sqlDA.Fill(ds);
}
}
am i passing the parameters in incorrectly?
when i do it in SQL server like so:
declare #OrgSubOrg OrgSubOrgValueType
insert into #OrgSubOrg values ('05%','00000000')
insert into #OrgSubOrg values ('03%','00000000')
------------ complete -----------------------------------
select * from myTable ex
where
year = '2013' and qtr = '1'
and EXISTS(
SELECT 1
FROM #OrgSubOrg tt
WHERE ex.org like tt.org
AND ex.orgsub = tt.suborg )
order by ex.org,year, qtr DESC
everything works like it should.
i also tried passing it in like so:
SqlParameter p = cmd.Parameters.Add(new SqlParameter("#OrgSubOrg", SqlDbType.Structured));
p.Value = FilteredOrgSubOrg;
but am getting the same error
The table type parameter '#OrgSubOrg' must have a valid type name.
could it be that i can't pass it to a SQL command, i have similar code in another place, that works great with a stored procedure...?
Set mapping to your type in SqlServer using TypeName property that: Gets or sets the type name for a table-valued parameter, that has to fix .
p.TypeName = "dbo.MyType";
Check as well Table-Valued Parameters post
Note that this may also happen when you're executing a stored procedure and you don't have the SqlCommand.CommandType set to CommandType.StoredProcedure, as such:
using (SqlCommand cmd = new SqlCommand("StoredProcName", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
}
You can get this error also when you wanna pass table params into stored procedure. There is happen if you use entity famework Context.Database.SqlQuery(). You must necessary set TypeName property for your table params.
SqlParameter codesParam = new SqlParameter(CODES_PARAM, SqlDbType.Structured);
SqlParameter factoriesParam = new SqlParameter(FACTORIES_PARAM, SqlDbType.Structured);
codesParam.Value = tbCodes;
codesParam.TypeName = "[dbo].[MES_CodesType]";
factoriesParam.Value = tbfactories;
factoriesParam.TypeName = "[dbo].[MES_FactoriesType]";
var list = _context.Database.SqlQuery<MESGoodsRemain>($"{SP_NAME} {CODES_PARAM}, {FACTORIES_PARAM}"
, new SqlParameter[] {
codesParam,
factoriesParam
}
).ToList();

Categories

Resources