public void CreateMySqlCommand()
{
SqlCommand myCommand = new SqlCommand();
myCommand.CommandText = "SELECT * FROM Categories ORDER BY CategoryID";
myCommand.CommandTimeout = 15;
myCommand.CommandType = CommandType.Text;
}
Can I use Sql Server functions in myCommand.CommandText and why?
If you mean, SQL Server user defined functions. Then, yes; you can use it normally like:
myCommand.CommandText = "SELECT fn_Yourfunctionname(#parameternames)";
myCommand.CommandType = CommandType.Text;
myCommand.Parameters.Add(new SqlParameter("#parameternames", ...
The reason it works is because this is the way that functions are called in SQL Server directly.
Another approach:
public T ExecuteScalarFunction<T>(string functionName, List<SqlParameter> parameters, SqlDbType returnSqlType) where T : new()
{
using (var conn = new SqlConnection(CTX.Database.GetDbConnection().ConnectionString))
{
if (conn.State != ConnectionState.Open)
conn.Open();
using (var cmd = new SqlCommand(functionName, conn)) {
cmd.CommandType = CommandType.StoredProcedure;
SqlCommandBuilder.DeriveParameters(cmd);
foreach (var parameter in parameters)
{
cmd.Parameters.Add(parameter);
}
cmd.Parameters.Add("#RETURN_VALUE", returnSqlType).Direction = ParameterDirection.ReturnValue;
cmd.ExecuteNonQuery();
return (T)cmd.Parameters["#RETURN_VALUE"].Value;
}
}
}
Related
I need a little help here. I'm trying to modify my functions in order to make them work in an Oracle database, I need to be able to get my Get and Create methods working on my Oracle database.
This is my create method:
public void CreateRow(Person person)
{
using SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("SP_InserNewRow", con);
{
cmd.CommandType = CommandType.StoredProcedure;
}
cmd.Parameters.AddWithValue("#CODE", person.CODE);
cmd.Parameters.AddWithValue("#NAME", person.NAME);
cmd.Parameters.AddWithValue("#LASTNAME", person.LASTNAME);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
This is my get method:
public IEnumerable<Person>GetPersonList
{
var listPerson = new List<Person>;
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("select * from myview", con);
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
var person = new Person();
person.CODE = Convert.ToInt32(dr["CODE"].ToString());
person.NAME = dr["NAME"].ToString();
person.LASTNAME = dr["LASTNAME"].ToString();
listPerson.Add(person);
}
con.Close();
}
return listPerson;
}
Now, I am trying to connect the above methods to an Oracle database.
I added this:
using Oracle.DataAccess.Client
using Oracle.DataAccess
Changed my string connection to this:
"DATA SOURCE=10.204.3.1:1521/PROD;" + "PERSIST SECURITY INFO=True;USER ID=username; password=password; Pooling =False;"
I started modifying the Get method:
public IEnumerable<Person>GetPersonList
{
var listPerson = new List<Person>();
using (OracleConnection con = new OracleConnection(connectionString2))
{
OracleCommand cmd = new OracleCommand("select * from myview", con);
cmd.Connection = con;
cmd.InitialLOBFetchSize = 1000;
cmd.CommandType = CommandType.StoredProcedure;
var list = new listPerson();
list.CODE = Convert.ToInt32(dr["CODE"].ToString());
list.NAME = dr["NAME"].ToString();
list.LASTNAME = dr["LASTNAME"].ToString();
listPerson.Add(list);
}
con.Close();
}
return listPerson;
I am kinda lost, can help me to modify my methods?
EDIT:
readonly string connectionString = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=xxxxxxxxx)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=PROD)));User Id=xxx;Password=xxxx;"
public IEnumerable<Person>GetPersonList
{
var listPerson = new List<Person>();
using (OracleConnection con = new OracleConnection(connectionString))
{
OracleCommand cmd = new OracleCommand("select * from myview", con);
cmd.Connection = con;
cmd.InitialLOBFetchSize = 1000;
cmd.CommandType = CommandType.Text;
con.Open();
OracleDataReader dr = cmd.ExecuteReader();
while (dr.Read()){
var list = new Person();
list.CODE = Convert.ToInt32(dr["CODE"].ToString());
list.NAME = dr["NAME"].ToString();
list.LASTNAME = dr["LASTNAME"].ToString();
listPerson.Add(list);
}
con.Close();
}
return listPerson;
}
My EDIT worked just fine. Thank you Steve :)
I've been searching but i do not fully understand how to execute the Stored Procedure through my application and then, commit the transaction. Do note that i am connected to an Oracle 11g database.
Take a look, this is my function, i tried to something like this but it does not seem correct to me:
public void CreateRow(Person person)
{
using SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("SP_InserNewRow", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#CODE", person.CODE);
cmd.Parameters.AddWithValue("#NAME", person.NAME);
cmd.Parameters.AddWithValue("#LASTNAME", person.LASTNAME);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
This is my Model cs file:
public class Person{
public int CODE { get; set; }
public string NAME { get; set; }
public string LASTNAME { get; set; }
}
This my my Oracle Stored Procedure:
create or replace PROCEDURE SP_InserNewRow(
CODE IN NUMBER,
NAME IN VARCHAR,
LASTNAME IN VARCHAR) AS
BEGIN
INSERT INTO MyTable(CODE,NAME,LASTNAME) VALUES (CODE, NAME, LASTNAME);
END SP_InserNewRow;
What is the correct way to execute it through MVC?
How can i COMMIT the transaction?
Is there exist any different while trying to execute it in Oracle11g and Oracle12?
EDIT:
readonly string connectionString = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=xxxxxxxxx)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=PROD)));User Id=xxx;Password=xxxx;"
public IEnumerable<Person>GetPersonList
{
var listPerson = new List<Person>();
using (OracleConnection con = new OracleConnection(connectionString))
{
OracleCommand cmd = new OracleCommand("select * from myview", con);
cmd.Connection = con;
cmd.InitialLOBFetchSize = 1000;
cmd.CommandType = CommandType.Text;
con.Open();
OracleDataReader dr = cmd.ExecuteReader();
while (dr.Read()){
var list = new Person();
list.CODE = Convert.ToInt32(dr["CODE"].ToString());
list.NAME = dr["NAME"].ToString();
list.LASTNAME = dr["LASTNAME"].ToString();
listPerson.Add(list);
}
con.Close();
}
return listPerson;
}
I suggest you use OracleConnection instead of SqlConnection
using Oracle.DataAccess;
using Oracle.DataAccess.Client;
public DataTable GetHeader_BySproc(string unit, string office, string receiptno)
{
using (OracleConnection cn = new OracleConnection(DatabaseHelper.GetConnectionString()))
{
OracleCommand cmd = new OracleCommand();
cmd.Connection = cn;
cmd.InitialLONGFetchSize = 1000;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#CODE", person.CODE);
cmd.Parameters.AddWithValue("#NAME", person.NAME);
cmd.Parameters.AddWithValue("#LASTNAME", person.LASTNAME);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
Also test your SP by executing in DBMS.
I have an update statement that works fine when I run it from SQL Developer. However, when I try to run it in C#, the program will freeze on the line that executes the command and not output anything. I have it defined as follows below:
private static OracleCommand cmd = new OracleCommand();
private static OracleConnection conn = new OracleConnection();
conn.ConnectionString = Properties.Settings.Default.myconstring;
cmd.Connection = conn;
cmd.CommandText = "UPDATE mytable SET PARAM1 = :param1 WHERE PARAM2 = :param2";
cmd.CommandType = CommandType.Text;
cmd.BindByName = true;
cmd.Parameters.Clear();
cmd.Parameters.Add(new OracleParameter(":param1", OracleDbType.Single)).Value = param1Val;
cmd.Parameters.Add(new OracleParameter(":param2", OracleDbType.Int32)).Value = param2Val;
conn.Open();
try {
cmd.ExecuteNonQuery(); //Freezes here
} catch(Exception e) {
MessageBox.Show(e.ToString());
}
conn.Close();
I have verified my values being put in are correct.
I'm trying to write a method which should communicate with database, but I'm not sure if my approach is right.
public void dbWorkerLogin(int workerNumber) {
// Connection string stored in "conn"
if (!new SqlCommand("Some Command WHERE id=" +workernumber,conn).executeReader().HasRows)
{
new SqlCommand("exec STORED_PROCEDURE1 " + workerNumber, conn).ExecuteNonQuery();
new SqlCommand("exec STORED_PROCEDURE2 " + workerNumber, conn).ExecuteNonQuery();
}
else
{
new SqlCommand("exec STORED_PROCEDURE3 " + workerNumber,conn).ExecuteNonQuerry();
}
1) Is it ok to write it like this and start each SqlCommand with keyword new? Or should I do something like:
SqlCommand command = new SqlCommand(null, conn);
command = ...;
and then recycle the variable 'command' or this way?
using(SqlCommand cmd = new SqlCommand("COMMAND", conn);
2) Will my procedures work or should I use SqlCommand.Prepare() function that will covert my data into correct datatypes? eg. workerNumber is int, but in database it is stored as decimal.
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parametres.Add("#id", SqlDbType.Decimal).Value = workNumber;
cmd.Prepare();
cmd.ExecuteNonQuery();
}
Can you please somehow sum up what to use, what better not to? Unfortunately I can't test that first code because of limited access to DB so I'm not sure if it can be executed without errors or not.
Thank you for any help on this subject!
EDIT:
After a few hours I reach to this stage:
public int getWorkerNumber(string uniqueID)
{
using (conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnect"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT number FROM worker WHERE workerID = #id",conn))
{
cmd.Parameters.Add("#id", SqlDbType.Decimal).Value = uniqueID;
using (SqlDataReader reader = cmd.ExecuteReader())
{
int answer;
while (reader.Read())
{
answer = (int)reader.GetDecimal(0);
}
return answer;
}
}
}
}
And this one:
public string dbLoginWorker(int workerNumber)
{
SqlCommand cmd;
SqlDataReader reader;
using (conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnect"].ConnectionString))
{
conn.Open();
cmd = new SqlCommand("SELECT column FROM table WHERE id= #workernumber", conn);
cmd.Parameters.Add("#workernumber", SqlDbType.Decimal).Value = workerNumber;
reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
cmd = new SqlCommand("STORED_PROCEDURE1", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal).Value = workerNumber;
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar).Value = "text";
cmd.Prepare();
reader.Close();
cmd.ExecuteNonQuery();
cmd.Dispose();
reader.Dispose();
return "procedure 1 executed";
else
{
cmd = new SqlCommand("STORED_PROCEDURE2", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal).Value = workerNumber;
cmd.Parameters.Add("#INT", SqlDbType.SmallInt).Value = 1;
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar).Value = "text";
cmd.Prepare();
reader.Close();
cmd.ExecuteNonQuery();
cmd.Dispose();
reader.Dispose();
return "procedure 2 executed";
}
}
}
Both methods are functional (if I did no mistake in rewriting :) ). I'm not sure which of these methods (1st or 2nd) are better in terms of stability and if this approach is better and more ressistant to SQL Injection. Can someone comment on this subject? Thank you again for any help!
1) It is best to always use USING blocks when possible. This includes SqlConnection, SqlCommand, SqlReader and other objects that implement IDisposable. USING blocks automatically close and dispose of the objects, so you do not have to do so.
2) I believe that you are using the Prepare() method in the wrong place. Look at the following StackOverflow article for proper usage:
PrepareMethodInstructions.
3) in the dbLoginWorker() method, the first query is just used to determine if rows are found. Therefore, I suggest changing the SELECT command to SELECT TOP 1 column FROM table WHERE id= #workernumber so that the query is faster and more efficient.
4) I do not believe your commands are subject to SQL Injection attacks because they are fully parameterized. Good job on that one.
5) As a general thought, I suggest reading up on refactoring techniques. Your dbLoginWorker() method could be made more readable and maintainable, as well as self-documenting, if you created three additional methods, one for each SQL command, and named them something appropriate. You could also setup a method for creating a connection based on a connection name, and you would not have as much duplicate code. For example:
public static SqlConnection GetConnection(string connectionName)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[connectionName].ConnectionString);
conn.Open();
return conn;
}
public string dbLoginWorker(int workerNumber)
{
using (conn = GetConnection("dbConnect"))
{
if (CanFindWorkerNumber(conn, workerNumber))
ExecuteProcedure1(conn);
else
ExecuteProcedure2(conn);
}
}
public bool CanFindWorkerNumber (SqlConnection conn, int workerNumber)
{
bool success = false;
using (SqlCommand cmd = new SqlCommand("SELECT TOP 1 column FROM table WHERE id= #workernumber", conn))
{
cmd.Parameters.Add("#workernumber", SqlDbType.Decimal);
cmd.Prepare();
cmd.Parameters[0].Value = workerNumber;
success = cmd.ExecuteScalar() != null;
}
return success;
}
public void ExecuteProcedure1(SqlConnection conn)
{
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE1", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal);
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar);
cmd.Prepare();
cmd.Parameters[0].Value = workerNumber;
cmd.Parameters[1].Value = "text";
cmd.ExecuteNonQuery();
}
}
public void ExecuteProcedure1(SqlConnection conn)
{
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE1", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal);
cmd.Parameters.Add("#INT", SqlDbType.SmallInt).Value);
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar);
cmd.Prepare();
cmd.Parameters[0] = workerNumber;
cmd.Parameters[1] = 1;
cmd.Parameters[2] = "text";
cmd.ExecuteNonQuery();
}
}
You could actually do this in one SQL commend. Right now you are pulling back a result set only to see if it has rows or not, then executing different commands based on that. You should be able to do that in one command, disposing of it and the connection appropriately:
var sql =
#"
IF EXISTS(Some Command WHERE id=#workernumber)
BEGIN
exec STORED_PROCEDURE1 #workernumber;
exec STORED_PROCEDURE2 #workernumber;
END
ELSE
exec STORED_PROCEDURE3 #workernumber;
";
Note that you're not vulnerable to SQL injection because you're not dealing with strings, only integers.
i m making dll class for stored procedure as...help me to correct it...my boss said that i m missing parameter values to return but i m not getting anything to correct it...
public class transactionService
{
SqlConnection cs;
private void OpenConnection()
{
cs = new SqlConnection();
cs.ConnectionString = "Data Source=IRIS-CSG-174;Initial Catalog=library_system;Integrated Security=True";
cs.Open();
}
public membership_details calculatefine()
{
OpenConnection();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Exec member_fine_detail";
cmd.Parameters.Add(new SqlParameter("member_id", SqlDbType.Int));
membership_details myObjec = new membership_details();
cmd.ExecuteNonQuery();
SqlDataReader sdr = cmd.ExecuteReader();
myObjec.fine_per_day = 0;
return myObjec;
help me to correct this code...i m trying to get fne_per_day as per member_id and after this reference is adding to return form in project from that according to member_id fine_per_day is calculated...as the creteria is like member_id=5,membership_desc=silver,gol,platinum,fineperday=30or 20or10
I think you will need something like this for returning the out parameter of your stored procedure:
public membership_details calculatefine()
{
OpenConnection();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Exec member_fine_detail";
cmd.Parameters.Add(new SqlParameter("#member_id", SqlDbType.Int));
//Sql parameter corresponding to the output parameter
cmd.Parameters.Add(new SqlParameter("#fine_per_day", SqlDbType.Int));
cmd.Parameters[cmd.Parameters.Count - 1].Direction = ParameterDirection.Output;
//execute the stored procedure
cmd.ExecuteNonQuery();
//obtain the value for the output parameter
myObjec.fine_per_day = (int)cmd.Parameters["#fine_per_day"].Value;
return myObjec;
}