MySql Entity Framework Select - c#

I am having trouble with an MySql query.
string strSql = "select SQL_CALC_FOUND_ROWS *, pv.* from products pv WHERE pv.name = 'Teddy Bear';";
strSql += "SET #resultCount = FOUND_ROWS();"
MySqlParameter parm = new MySqlParameter("#resultCount",MySqlDbType.Int32)
parm.Direction = ParameterDirection.Output;
var result = ObjectContext.ExecuteStoreQuery<Product>(strSql,parm);
return result;
The Error returned is
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL = FOUND_ROWS()' at line 1
How do I get #resultCount to return the total record count

When creating the parameter I think you need to specify the name without #.
Also, you'll want to specify the parameter direction; I think that by default it's input only, meaning you need to provide a value that will be inserted into the command; what you want is output. You can specify the direction through some overloads when creating the parameter or by setting a property - don't know if the syntax differs from other providers as I haven't worked with the MySql one in quite some time, but it should be:
parm.Direction = ParameterDirection.Output;

Related

Query return on C#/mysql

I have in my class "fattura" this
public string sommaFattura(String costo)
{
MySqlCommand command = new MySqlCommand();
String sumQuery = "SELECT SUM(`prezzo`) FROM `fatturetemp`";
command.CommandText = sumQuery;
command.Connection = conn.getConnection();
command.Parameters.Add("#prezzo", MySqlDbType.Int32).Value = costo;
conn.openConnection();
//Need the command for take the result
conn.closeConnection();
}
What is the command for take the result of Sum query?
I want use this command, insert in a variable. Can you correct me?
I think the command you want is
command.ExecuteScalar();
However, note, Execute Scalar is intended that the result will return a single row, single column which your query does without regard to your parameter. However your query does not specifically make sense either..
Now your query itself. You have an explicit prezzo which would imply an existing column name and not that of a parameter. It would have to a numeric field for obvious reasons to sum it.
Now you also have an expected string coming in via "costo" parameter to the function call. If your intent is to have the incoming string be representative of a known column of the table, this is not going to work for you. You would have to build the SQL command with that explicit column name, or build doing dynamic-sql, but that would really be too much.
The concern with building a SQL statement with string parameters is you would be open to SQL-injection, especially if web-based. If your incoming string is coming from a controlled source, such as you are presenting a list of columns to a user and they can only pick one such column. Or, you have buttons on a screen asking for a sum of a certain thing, and YOU control that column name you would be in a better condition, but still be cautious passing parameter to build out SQL.
Say for example your table has numeric fields of qtySold and dollarSales. You want either the sum of either of these columns and are passing one of these respective strings into the function such as
var qtySoldAnswer = sommaFattura( "qtySold" );
or
var dollarSalesAnswer = sommaFattura( "dollarSales" );
Then your function would be CLOSER to...
public string sommaFattura(String costo)
{
MySqlCommand command = new MySqlCommand();
command.CommandText = "SELECT SUM(" + costo + ") FROM fatturetemp";
command.Connection = conn.getConnection();
conn.openConnection();
var answer = command.ExecuteScalar();
conn.closeConnection();
// I would put a breakpoint in here to see the results.
// you can then format the answer such as decimal point, etc.
return answer.ToString();
}
AGAIN, ONLY if YOU have control of the column name you are trying to send in. Someone could do sql-injection and do a lot of damage. I would only do with heavily controlled consideration and explicitly validating the columns you WOULD allow, and if so, set your variable at that point. Don't allow for any more or less than the column name. No special characters, quotes, comments, sql-terminator and new statement...
But hopefully this clarifies what I THINK you are trying to accomplish.

Passing in Oracle Parameter to SQL string

I'm having a problem where I don't know how I'm supposed to pass in an Oracle parameter where the C# type is a string and the Oracle type is a Varchar2.
Currently I'm passing in this string as CMS','ABC thinking that Oracle will add in the '' that surround this string making it a varchar2 that looks like 'CMS','ABC'.
This works for a single string like CMS but when the value is something longer, like something typically in a IN (list) command the parameter won't be passed in correctly.
This is the code I'm referring too.
string sql = 'SELECT name FROM Pers p WHERE p.FirstName IN (:names)';
The below works when the value of :names being passed in is CML without any quotes.
OracleParameter param = new OracleParameter(":names", OracleDbType.Varchar2, "CML", ParameterDirection.Input);
Below doesn't work when the value of :names being passed in is CML','ABC with quotes on the inside.
OracleParameter param = new OracleParameter(":names", OracleDbType.Varchar2, "CML','ABC", ParameterDirection.Input);
Why is that?
Does Oracle add in single quotes around the parameter when it's passed into the sql statement? Why doesn't it add quotes around the second case?
ODP.NET parameters do not work with multiple, comma separated values. Each parameter is treated as a single value, whatever kind of quotes it contains.
Oracle does not add quotes around parameter values when passed to a query. Quotes are just a way to write a VARCHAR value in a query, but when using parameters, Oracle doesn't "replace your parameter with its value then execute the query", as this would allow SQL injection.
If that was the case, imagine your parameter value was: "CML', 'ABC');DROP DATABASE Test;--". Oracle would then execute SELECT name FROM Pers p WHERE p.FirstName IN ('CML', 'ABC');DROP DATABASE Test;--'!
See this question for ideas on how to solve your problem: Oracle Parameters with IN statement?
From your comments/answers I was able to come up with this solution. I hope it helps others who come.
To get around ODT.NET parameters not working with multiple comma separated values you can divide each value into its own parameter. Like the following.
string allParams = "CML, ABC, DEF";
string formattedParams = allParams.Replace(" ", string.Empty); // Or a custom format
string [] splitParams = formattedParams.Split(',');
List<OracleParamter> parameters = new List<OracleParameter>();
string sql = #"SELECT * FROM FooTable WHERE FooValue IN (";
for(int i = 0; i < splitParams.Length; i++)
{
sql += #":FooParam" + i + ",";
parameters.Add(new OracleParameter(":FooParam" + i, OracleDbType.Varchar2, splitParams[i], ParameterDirection.Input));
{
sql = sql.Substring(0, (sql.Length - 1));
sql += ')';
The string sql will now have this as it's value: SELECT * FROM FooTable WHERE FooValue IN (:FooParam0,:fooParam1, etc...)
This will solve the problem.
Another approach would be to add in a bunch of OR clauses for each parameter. The above example is better since you don't write a bunch of OR clauses though.

I am getting the "Must declare the scalar variable "#Val1"" error when inserting the record using C#

When I am running the following code
if (NewButtonClicked == true) {
string sql = "SELECT MAX(location_id)+1 FROM locations";
OdbcCommand my_odbc_cmd = new OdbcCommand(sql, my_odbc_connection);
OdbcDataReader my_data_reader;
int new_id = 0;
my_data_reader = my_odbc_cmd.ExecuteReader();
if (my_data_reader.HasRows)
{
my_data_reader.Read();
new_id = (int)my_data_reader[0];
}
my_data_reader.Close();
textBoxLocationID.Text = new_id.ToString();
sql = "INSERT INTO locations (location_id,location,latitude,longitude,city,"
+ "state_province,country,continent) VALUES (#Val1,'#Val2',#Val3,#Val4,'#Val5','#Val6','#Val7','#Val8')";
my_odbc_cmd.Connection = my_odbc_connection;
my_odbc_cmd.CommandText = sql;
my_odbc_cmd.Parameters.AddWithValue("#Val1", new_id);
my_odbc_cmd.Parameters.AddWithValue("#Val2", textBoxName.Text);
my_odbc_cmd.Parameters.AddWithValue("#Val3", textBoxLatitude.Text);
my_odbc_cmd.Parameters.AddWithValue("#Val4", textBoxLongitude.Text);
my_odbc_cmd.Parameters.AddWithValue("#Val5", textBoxCity.Text);
my_odbc_cmd.Parameters.AddWithValue("#Val6", textBoxState_Province.Text);
my_odbc_cmd.Parameters.AddWithValue("#Val7", textBoxCountry.Text);
my_odbc_cmd.Parameters.AddWithValue("#Val8", textBoxContinent.Text);
my_odbc_cmd.CommandType = CommandType.Text;
my_odbc_cmd.ExecuteNonQuery();
}
It is giving me "Must declare the scalar variable "#Val1"" when the execution is reached at:
my_odbc_cmd.ExecuteNonQuery();
How can I solve this error. Can anyone help me? Database used at the backend is SQL Server 2008 R2. I am using the ODBC connection to connect to the database.
This probably means that new_id is null. Parameters with a value of null are not sent. You need to pass DBNull.Value instead. Crazy but true.
my_odbc_cmd.Parameters.AddWithValue("#Val1", ((object)new_id) ?? DBNull.Value);
Also: '#Val2' (and similar) are very wrong. You almost certainly mean just #Val2, no quotes.
According to the "Working with Parameter Placeholders" section on the MSDN page Configuring Parameters and Parameter Data Types, the Odbc datasource supports only positional parameters via ? in the query text, not named parameters (such as #Val1), which are supported only by SqlClient.
Additionally as Marc Gravell indicates, you shouldn't be quoting the parameters in your query.
Try changing your SQL to:
sql = "INSERT INTO locations (location_id,location,latitude,longitude,city,"
+ "state_province,country,continent) VALUES (?,?,?,?,?,?,?,?)";

How can I update data in CLOB fields using a >> prepared query << with ODP (Oracle.DataAccess)?

I'm trying to execute a prepared sql query which updates CLOB fields in an Oracle 10g database (10.2.0.1).
If I execute the following query from inside SQL Developer and supply the values for the placeholders, there is no prblem. If I however execute it through an OracleCommand (Oracle.DataAccess.dll, version 1.102.0.1 (I think), .NET Framework 3.5),
I get the error message below. Note that we are not using the default oracle client as we require bulk insertion. The given ODP version and .NET Framework version are unfortunately a hard requirement and we may not change that.
Query:
UPDATE master_table
SET description = :description,
modification_notes = :modification_notes
WHERE master_id = :master_id;
Error:
ORA-00932: inconsistent datatypes: expected - got CLOB
Further Inormation:
Parameters are assigned as follows:
var param_description = new OracleParameter(":description", OracleDbType.Clob);
param_description.Value = "Test";
I have tried the following things:
insert to_clob() into the SQL query
assign a Oracle.DataAccess.Types.OracleClob object to the parameter.
I have also found the following description, but I would really want to be able to keep the prepared query.
How to insert CLOB field in Oracle using C#
Is it possible to do this through a prepared query?
I've attached a complete example which produces the error. DESCRIPTION and MODIFICATION_NOTES are two columns of type CLOB in the database.
Input data:
connection: OracleConnection to the database
master_id: primary key to filter for
Code:
Disclaimer: I typed the following example by hand, there might be mistakes which are not in the actual code
var query = "UPDATE master_table " +
"SET description = :description " +
" modification_notes = :modification_notes " +
"WHERE master_id = :master_id";
var param_master_id = new OracleParameter(":master_id", OracleDbType.Int64);
param_master_id.Value = master_id;
var param_description = new OracleParameter(":description", OracleDbType.Clob);
param_description.Value = "Test1";
var param_master_id = new OracleParameter(":modification_notes", OracleDbType.Clob);
param_description.Value = "Test2";
IDbCommand command = new OracleCommand(query, connection);
command.parameters.Add(param_master_id);
command.parameters.Add(param_description);
command.parameters.Add(param_modification_notes);
command.ExecuteNonQuery(); // this line throws an exception
You need to set this to true if you want to bind by name. Default is bind by the order of the parameter added.
cmd.BindByName = true;
Edit: My answer below applies for typical use of Clobs where the size is greater than 32k (what they were designed for). If you know you will always be binding less than 32k bytes, or 16k characters in the usual case of unicode you can bind as Varchar2 and free yourself from having to create a temporary lob.
--
Keep in mind that a LOB in an oracle column is really a LOB Locator, a pointer to the actual data. Before you can update a CLOB column with that Lob Locator, you need to create and populate a temporary CLOB first.
In the ODP.NET samples directory in your Oracle Home there should be a LOB directory, in there it looks like samples5.cs might be a good place to start. Here is a snippet from it:
// Set the command
OracleCommand cmd = new OracleCommand(
"update multimedia_tab set story = :1 where thekey = 1");
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
// Create an OracleClob object, specifying no caching and not a NCLOB
OracleClob clob = new OracleClob(con, false, false);
// Write data to the OracleClob object, clob, which is a temporary LOB
string str = "this is a new story";
clob.Write(str.ToCharArray(), 0, str.Length);
// Bind a parameter with OracleDbType.Clob
cmd.Parameters.Add("clobdata",
OracleDbType.Clob,
clob,
ParameterDirection.Input);
try
{
// Execute command
cmd.ExecuteNonQuery();
See the accepted answer for the actual solution.
[Edit: Former suspected answer]:
After several days of testing and debugging I found the solution which was so far away from everything I considered:
Apparently, you need to bind all Clob fields first before binding anything else - even when using actual placeholders instead of using :1, :2 etc.
Changing the bind order (i.e. the order of the AddParameter calls) fixed it.
Try This :
string Query3 = " DECLARE " +
"str varchar2(32767); " +
" BEGIN " +
" str := '" + base64ImageRepresentationLogo + "'; " +
" update map_general_settings set value=str where DESC_AR='LOGO_IMG' ; END; ";
command.CommandText = Query3;
command.ExecuteNonQuery();

Error converting data type nvarchar to bigint

Hello I am getting this error -
'Error converting data type nvarchar to bigint'
while running this is the code:
string idString = "1,2,3,4";
string updateSql = "UPDATE DistinctClubcard SET ProcessedYorN = 'Y' " + "WHERE CLUBCARD_NUMBER in (#flag) ";
SqlCommand UpdateCmd = new SqlCommand(updateSql, cn);
UpdateCmd.Parameters.Add(new SqlParameter("#flag", SqlDbType.NVarChar, 2000));
UpdateCmd.Parameters["#flag"].Value = idString ;
UpdateCmd.ExecuteNonQuery();
This won't work - A SQL IN (...) query needs an array of sql parameters, it will not just work with passing a single string parameter. Instead use a separate parameter for each value and an array of integer values:
string idString = "1,2,3,4";
var ids = idString.Split(',').Select(x => int.Parse(x)).ToArray();
for(int i =0;i< ids.Length;i++)
{
UpdateCmd.Parameters.Add(new SqlParameter("#flag"+i, SqlDbType.BigInt));
UpdateCmd.Parameters["#flag"+i].Value = ids[i];
}
Of course that also changes your query where you have to account for your parameters:
string flags = string.Join(",", ids.Select((s, i) => "#flag" + i));
string updateSql = string.Format("UPDATE DistinctClubcard SET ProcessedYorN = 'Y' WHERE CLUBCARD_NUMBER in ({0})",flags);
The parameter is going to passed to SQL Server as a single value, not as a replacement within the query. There are different ways you could send multiple values, including (for SQL Server 2008) table-valued parameters, or possibly formatting the parameter as XML to be parsed on the SQL Server side. (I used this solution once, but I wouldn't recommend it unless you can't find another solution.)
See this question on SO for more in-depth answers: Passing List<> to SQL Stored Procedure

Categories