Must declare the scalar variable "#ChargeRate" - sqlcommand

Why do I get the error Must declare the scalar variable "#ChargeRate"?
public static void InsertSqlSerwer2(BatteryFullInfo info)
{
SqlConnection MSDEconn;
MSDEconn = new SqlConnection();
MSDEconn.ConnectionString = #"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\HOME\Documents\NewDataBase.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
MSDEconn.Open();
string komenda = "INSERT into Battery_Information VALUES (#ChargeRate, #Id, #DischargeRate, #RemainingCapacity, #Voltage, #BatteryLifePercent, #ChargeStatus)";
SqlCommand MSDEcommand = new SqlCommand(komenda, MSDEconn);
MSDEcommand.Parameters.AddWithValue("#ChargeRate", info.ChargeRate);
MSDEcommand.Parameters.AddWithValue("#Id", info.IdBateria);
MSDEcommand.Parameters.AddWithValue("#DischargeRate", info.DischargeRate);
MSDEcommand.Parameters.AddWithValue("#RemainingCapacity", info.RemainingCapacity);
MSDEcommand.Parameters.AddWithValue("#Voltage", info.Voltage);
MSDEcommand.Parameters.AddWithValue("#BatteryLifePercent", info.BatteryLifePercent);
MSDEcommand.Parameters.AddWithValue("#ChargeStatus", info.ChargeStatus);
MSDEcommand.Parameters.Clear();
MSDEcommand.ExecuteNonQuery();
MSDEconn.Close();
}

Because you are clearing your parameters. You go through all of the effort to AddWithValue, and then you execute MSDEcommand.Parameters.Clear(), which gets rid of them all. Remove that line and I think this will work.

Related

How to use prepared statement that returns resultset with jdbcTemplate in spring mvc 3?

Here is my code which uses jdbcTemplate
String SQL = "select branch from branchTable where branch_name = '" + branch + "'";
ArrayList<String> branchList = (ArrayList<String>) jdbcTemplateObject.query(SQL, new RowMapper() {
public Object mapRow(ResultSet resultSet, int i) throws SQLException {
return resultSet.getString("city_desc");
}
});
return branchList;
Now i want to be able to use preparedstatement with a query like "select branch from branchTable where branch_name = ?"
How can i do that with jdbcTemplate ?
Examples i searched show demonstration on how to use it with update or insert query, but not with select query..
Please help.
JdbcTemplate has another query() method which takes arguments of the prepared statement as parameter:
jdbcTemplateObject.query(SQL, new Object[] {branchName}, new RowMapper() {...});
Note that:
SQL should be named sql
You should use List and not ArrayList. Nothing in the javadoc guarantees that an ArrayList is returned. And you shouldn't care about the concrete type of list returned.
You should use a RowMapper<String> and not a raw RowMapper.

Dapper with Oracle passing in DbParameter

I'm trying out Dapper with Oracle and I was trying to run a multi-resultset query but Oracle requires a dbtype of refcursor.
StringBuilder query = new StringBuilder("BEGIN ");
query.Append("OPEN :rs1 FOR SELECT * FROM Table1 where key=:KEY; ");
query.Append("OPEN :rs2 FOR SELECT * FROM Table2 where key=:KEY; ");
query.Append("END;");
Is there a way to pass an OracleParameter (maybe as DbParameter?) to Dapper? When I tried, it threw an error.
What is the advantage of using the DynamicParameter vs. using a DbParameter (assuming types are known etc.)?
A new interface was added in the most recent build that allows more control over the parameter - it was added to support TVPs in SQL server, but should work in this scenario. However, I'm also fairly content to add special casing for any types that look like dbparameter - and add them directly, which would allow you to add an oracleparameter directly.
DynamicParameters is about how many parameters to add, so it is a bit orthogonal to the value vs DbParameter discussion. At the moment, the code generally prefers to take control of adding parameters itself, so the caller just knows "an int named id with value 7" - not any ado.net details. But it could do.
Edit: if you really want to work with lists-of-parameters (i.e. List<DbParameter> etc), then you can do that with something like:
public class DbParams : Dapper.SqlMapper.IDynamicParameters,
IEnumerable<IDbDataParameter>
{
private readonly List<IDbDataParameter> parameters =
new List<IDbDataParameter>();
public IEnumerator<IDbDataParameter> GetEnumerator() {
return parameters.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public void Add(IDbDataParameter value)
{
parameters.Add(value);
}
void Dapper.SqlMapper.IDynamicParameters.AddParameters(IDbCommand command,
Dapper.SqlMapper.Identity identity)
{
foreach (IDbDataParameter parameter in parameters)
command.Parameters.Add(parameter);
}
}
with usage like:
public void TestCustomParameters()
{
var args = new DbParams {
new SqlParameter("foo", 123),
new SqlParameter("bar", "abc")
};
var result = connection.Query("select Foo=#foo, Bar=#bar", args).Single();
int foo = result.Foo;
string bar = result.Bar;
foo.IsEqualTo(123);
bar.IsEqualTo("abc");
}
which passes the test.
However, I must stress that I would prefer not to encumber the calling code with db-parameter knowledge unless it really really needs to know; I would by-far prefer:
var args = new {
foo = 123, bar = "abc"
};
which does exactly the same thing, but without dropping to ADO.NET; this can be especially important if you are using a "decorated" ADO.NET connection (for example, mini-profiler) - in which case the layer you get is not an OracleCommand / OracleConnection etc - it is abstracted. This means that forcibly adding an OracleParameter may not always work - but adding a parameter with name "foo" and value 123 - that is pretty reliable.

passing an object having array to oracle stored procedure

I've a class "User" as follows:
public class User{
private String firstname;
private String lastname;
private String[] departments;
}
I want to pass an object of User type to my oracle stored procedure that takes an object type as parameter. So I did this to achieve my solution:-
1. Created USER_SEARCH_OBJ as a type in database as follows:-
create or replace
TYPE USER_SEARCH_OBJ AS OBJECT (
FIRST_NAME VARCHAR2(256),
LAST_NAME VARCHAR2(256),
DEPARTMENTS TABLE_OF_VALUES,
);
2. Created TABLE_OF_VALUES as a type in database as follows:-
create or replace TYPE TABLE_OF_VALUES AS TABLE OF VARCHAR2(20);
3. Passed the User object from Java class as follows:-
Object[] departments = {"1","2"};
StructDescriptor objDescriptor = StructDescriptor.createDescriptor("USER_SEARCH_OBJ", conn.getMetaData().getConnection());
ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor("TABLE_OF_VALUES", conn.getMetaData().getConnection());
ARRAY departmentArr = new ARRAY(arrayDescriptor, conn.getMetaData().getConnection(), departments );
Object[] userProperties = new Object[2];
userProperties [0] = "paras";//first_name
userProperties [1] = "anand";//last_name
userProperties [2] = departmentArr ;//department array
STRUCT searchObj = new STRUCT(objDescriptor, conn.getMetaData().getConnection(), userProperties );
CallableStatement cStmt = conn.prepareCall("PCK_SEARCH2.USER_SEARCH(?,?)");
cStmt.setObject(1, searchObj);
cStmt.registerOutParameter(2, OracleTypes.CURSOR);
cStmt.execute();
But when I run this code I get an exception as follows:-
java.sql.SQLException: Inconsistent java and sql object types
at oracle.sql.StructDescriptor.toOracleArray(StructDescriptor.java:709)
at oracle.sql.StructDescriptor.toArray(StructDescriptor.java:1296)
at oracle.sql.STRUCT.<init>(STRUCT.java:165)
at com.ensenda.lmp.web.controller.User.main(User.java:75)
This exception comes at the following line of code:-
STRUCT searchObj = new STRUCT(objDescriptor, conn.getMetaData().getConnection(), userProperties );
Please let me know where I'm going wrong.
Firstly I think you should get an ArrayOutOfBoundException because you have declared an Object[2] and trying to put a 3rd element into it. Considering that is a typo.
For the original problem instead of using setObject you can use
*JDBCUtil.setStruct(conn,cStmt,1,"USER_SEARCH_OBJ",userProperties);*

ODP.NET and parameters

I have built a common app that works with PostgreSQL and should work on Oracle.
However i'm getting strange errors when inserting records through a parametrized query.
My formatted query looks like this:
"INSERT INTO layer_mapping VALUES (#lm_id,#lm_layer_name,#lm_layer_file);"
Unlike Npgsql which documents how to use the parameters, i could not found how Oracle "prefers" them to be used. I could only find :1, :2, :3, for example.
I do not wanto use sequential parameters, i want to use them in a named way.
Is there a way to do it? Am i doing something wrong?
Thanks
You can use named parameters with ODP.NET like so:
using (var cx=new OracleConnection(connString)){
using(var cmd=cx.CreateCommand()){
cmd.CommandText="Select * from foo_table where bar=:bar";
cmd.BindByName=true;
cmd.Parameters.Add("bar",barValue);
///...
}
}
I made this lib https://github.com/pedro-muniz/ODPNetConnect/blob/master/ODPNetConnect.cs
so you can do parameterized write and read like this:
ODPNetConnect odp = new ODPNetConnect();
if (!String.IsNullOrWhiteSpace(odp.ERROR))
{
throw new Exception(odp.ERROR);
}
//Write:
string sql = #"INSERT INTO TABLE (D1, D2, D3) VALUES (:D1, :D2, :D3)";
Dictionary<string, object> params = new Dictionary<string, object>();
params["D1"] = "D1";
params["D2"] = "D2";
params["D3"] = "D3";
int affectedRows = odp.ParameterizedWrite(sql, params);
if (!String.IsNullOrWhiteSpace(odp.ERROR))
{
throw new Exception(odp.ERROR);
}
//read
string sql = #"SELECT * FROM TABLE WHERE D1 = :D1";
Dictionary<string, object> params = new Dictionary<string, object>();
params["D1"] = "D1";
DataTable dt = odp.ParameterizedRead(sql, params);
if (!String.IsNullOrWhiteSpace(odp.ERROR))
{
throw new Exception(odp.ERROR);
}
Notes: you have to change these lines in ODPNetConnect.cs to set connection string:
static private string devConnectionString = "SET YOUR DEV CONNECTION STRING";
static private string productionConnectionString = "SET YOUR PRODUCTION CONNECTION STRING";
And you need to change line 123 to set environment to dev or prod.
public OracleConnection GetConnection(string env = "dev", bool cacheOn = false)

Linq to sql truncating string returned by Stored Procedure

I have asked this question before. but i was not able to get any answer. may be i wasnt very clear. let me give some more details.
I have a SP which returns a long string. here is dbml file code
[Function(Name="dbo.spX")]
public ISingleResult<spXResult> spX([Parameter(DbType="VarChar(8000)")] string str)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), str);
return ((ISingleResult<spXResult>)(result.ReturnValue));
}
and here is spXResult class
public partial class spXResult
{
private string _XML_F52E2B61_18A1_11d1_B105_00805F49916B;
public spXResult()
{ }
[Column(Name="[XML_F52E2B61-18A1-11d1-B105-00805F49916B]",
Storage="_XML_F52E2B61_18A1_11d1_B105_00805F49916B",
DbType="NText", UpdateCheck=UpdateCheck.Never)]
public string XML_F52E2B61_18A1_11d1_B105_00805F49916B
{
get
{
return this._XML_F52E2B61_18A1_11d1_B105_00805F49916B;
}
set
{
if ((this._XML_F52E2B61_18A1_11d1_B105_00805F49916B != value))
{
this._XML_F52E2B61_18A1_11d1_B105_00805F49916B = value;
}
}
}
}
and here is my code
ISingleResult<spXResult> result = ctx.spX("1234");
string returnStr = result.First().XML_F52E2B61_18A1_11d1_B105_00805F49916B;
everything is fine, when the result is not a long string, but as soon as the sp returns a very long string, it truncates the result. i have no clue why.. can someone please help.
thanks
The only thing fishy I can spot is this - here in the declaration, you hvae:
public ISingleResult<spXResult> spX([Parameter(DbType="VarChar(8000)")] string str)
(DbType=VARCHAR(8000)) - which is ANSI (non-Unicode), but then in the column declaration you use NTEXT - first of all, that's UNICODE (2-byte per character), and why NTEXT?? Above you have VARCHAR?
[Column(Name="[XML_F52E2B61-18A1-11d1-B105-00805F49916B]",
Storage="_XML_F52E2B61_18A1_11d1_B105_00805F49916B",
DbType="NText", UpdateCheck=UpdateCheck.Never)]
That seems a bit odd.......
Can you try to make it the same in both places? E.g. VARCHAR(8000) in both cases??
Marc
LinqToSql splits the XML result set into chunks, so you need to run a loop like this:
ISingleResult<spXResult> result = ctx.spX("1234");
string xml = "";
foreach (var x in result)
xml += x.XML_F52E2B61_18A1_11d1_B105_00805F49916B;
Or using LINQ:
string xml = result.Aggregate("", (current, x) => current + x.XML_F52E2B61_18A1_11d1_B105_00805F49916B);
Just change your sp from
SELECT ...
FROM MyTable
FOR XML AUTO
to
DECLARE #ResultXML xml
SET #ResultXML =
(SELECT ...
FROM MyTable
FOR XML AUTO)
SELECT #ResultXML as [MyXML]
and recreate linq method

Resources