I am trying to write c# function to read some data from oracle table
My functions:
public static writeConsole(string query, string connectionString, string driver)
{
//driver = Oracle.ManagedDataAccess.Client
using (var conn = DbProviderFactories.GetFactory(driver).CreateConnection())
{
using (var cmd = conn.CreateCommand())
{
cmd.Connection.ConnectionString = connectionString;
cmd.CommandType = CommandType.Text;
cmd.CommandText = query;
foreach (var item in ReadDouble(cmd))
{
Console.WriteLine(item);
}
}
}
}
private static IEnumerable<double> ReadDouble(IDbCommand cmd)
{
using (var r = cmd.ExecuteReader())
{
while (r.Read())
yield return r.GetDouble(0);
}
}
There is no problem in connection, nor executing query.
When I read data from oracle table in type number(9) it returns proper values I am expecting.
When I read data from table, where type is number(9,2) it returns empty value (like empty table).
Notice: This is only sample of the code. It has to be written using IDb interfaces
Thank you for help
Possibly it is problem with type mapping. Try this:
http://docs.oracle.com/html/E10927_01/featSafeType.htm#i1008428
And this:
https://community.oracle.com/message/3582080
public static writeConsole(string query, string connectionString, string driver)
{
//driver = Oracle.ManagedDataAccess.Client
using (var conn = DbProviderFactories.GetFactory(driver).CreateConnection())
{
using (var cmd = conn.CreateCommand())
{
cmd.Connection.ConnectionString = connectionString;
cmd.CommandType = CommandType.Text;
cmd.CommandText = query;
var reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader[0]+"");
}
}
}
}
You can Try
OracleConnection conn = new OracleConnection(connectionString);
OracleCommand cmd = new OracleCommand(query, conn);
if (conn.State == ConnectionState.Closed)
conn.Open();
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader[0]+"");
}
Related
I am having a function which calls different functions that connect to the mysql database and queries the database. Here I am not sure how can I reuse my conn and cmd to make more efficiency in the code. To have the connection creaeted in Validation() once and reuse them in the other function wherever I am trying to connect to database. Below is what I am doing
private static void Validation(List<Employee> EmpList, string Group)
{
ValidateName(EmpList, Group);
ValidateDept(EmpList, Group);
}
public static void ValidateName(List<Employee> EmpList, string Grp)
{
var connStr = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
string selectQuery;
for (int i = 0; i < EmpList.Count; i++)
{
selectQuery = "Select Name from Employee where Group = #Group AND #Name in (FirstName, LastName);";
using (MySqlConnection conn = new MySqlConnection(connStr))
using (MySqlCommand cmd = new MySqlCommand(selectQuery, conn))
{
cmd.Parameters.Add("#Group", MySqlDbType.VarChar).Value = Grp;
cmd.Parameters.Add("#Name", MySqlDbType.VarChar).Value = EmpList[i].Name;
conn.Open();
var reader = cmd.ExecuteReader();
List<string> lineList = new List<string>();
while (reader.Read())
{
lineList.Add(reader.GetString(0));
}
if (lineList.Count <=0)
{
WriteValidationFailure(EmpList[i], "Failed");
}
conn.Close();
}
}
}
public static void ValidateBreedingDept(List<Employee> EmpList, string Grp)
{
var connStr = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
string selectQuery;
for (int i = 0; i < EmpList.Count; i++)
{
selectQuery = "Select DepartmentName from Department where Group = #Group AND DepartmentName = #Dept;";
using (MySqlConnection conn = new MySqlConnection(connStr))
using (MySqlCommand cmd = new MySqlCommand(selectQuery, conn))
{
cmd.Parameters.Add("#Group", MySqlDbType.VarChar).Value = Grp;
cmd.Parameters.Add("#Dept", MySqlDbType.VarChar).Value = EmpList[i].Dept;
conn.Open();
var reader = cmd.ExecuteReader();
List<string> lineList = new List<string>();
while (reader.Read())
{
lineList.Add(reader.GetString(0));
}
if (lineList.Count <= 0)
{
WriteValidationFailure(listOfMouse[i], "Failed");
}
conn.Close();
}
}
}
I am new to connecting to database and querying from c#. And also how to rewrite the queries to use Prepare statements. I understand I can use cmd.Prepare() but can I reuse the parameters from one function in to another.
"reuse my conn and cmd to make more efficiency in the code"
You don't need to worry about that. C# takes care of it by using something called connection pool.
All "closed" connections do not really close the underlying connection but rather returned to the connection pool for later use which is exactly what you are trying to do
Read more on MSDN
I Have a question regarding SQL commands. I could not seems to get the while loop running under the "while(dr.read())". Below Are my sample code in C# Windows Form.
Thank You.
cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM network";
MySqlDataReader dr;
dr = cmd.ExecuteReader();
while (dr.Read())
{
string datasource = dr[1].ToString();
string datadestination = dr[2].ToString();
if (source == datasource && destination == datadestination)
{
int newcounter;
newcounter = Convert.ToInt32(dr[4]) + 1;
cmd.CommandText = "UPDATE network set counter = #nnnewcounter";
cmd.Parameters.AddWithValue("#nnnewcounter", newcounter);
}
else
{
cmd.CommandText = "INSERT INTO network(source,destination,length,counter) VALUES (#sssource,#dddestination,#lllength,#cccounter)";
cmd.Parameters.AddWithValue("#sssource", source);
cmd.Parameters.AddWithValue("#dddestination", destination);
cmd.Parameters.AddWithValue("#lllength", length);
cmd.Parameters.AddWithValue("#cccounter", 1);
}
}
You have a few issues with this first you’re reusing the same command and using different parameters at which point you should clear them. It is also not clear if your are Opening the connection for the datareader. I would therefore move the insert and update outside the SQLDataReader as it would make the code easier to read.
using (SqlConnection connection = new SqlConnection(ConnString))
{
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "SELECT * FROM network";
cmd.Connection.Open();
using (MySqlDataReader dr = cmd.ExecuteReader())
{
if (dr .HasRows)
{
while (dr.Read())
{
string datasource = dr[1].ToString();
string datadestination = dr[2].ToString();
if (source == datasource && destination == datadestination)
{
int newcounter;
newcounter = Convert.ToInt32(dr[4]) + 1;
Updateddos_network(newcounter);
}
else
{
Savedoss_network(source,destination, length, 1);
}
}
else
{
//No rows found
}
}
}
}
Then outside the method in the same class you could have.
private void Updateddos_network(int newcounter)
{
using (SqlConnection connection = new SqlConnection(ConnString))
{
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "UPDATE ddos_network set counter = #nnnewcounter";
cmd.Parameters.AddWithValue("#nnnewcounter", newcounter);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
}
private void Insertddos_network(string source, string destination, int length, int counter)
{
using (SqlConnection connection = new SqlConnection(ConnString))
{
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "INSERT INTO ddos_network(source,destination,length,counter) VALUES (#sssource,#dddestination,#lllength,#cccounter)";
cmd.Parameters.AddWithValue("#sssource", source);
cmd.Parameters.AddWithValue("#dddestination", destination);
cmd.Parameters.AddWithValue("#lllength", length);
cmd.Parameters.AddWithValue("#cccounter", counter);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
}
If you were to refactor your code further you could have a Save method for your ddos_network object which could then be used to demine if your object is being updated or inserted based upon if the current object has an Id for example.
I keep getting this error
There is already an open datareader associated with this command which must be closed first.
at this line of code:
using (SqlDataReader rd = command.ExecuteReader())
I have tried to close all other SqlDataReader's in class but it didn't work.
public int SifreGetir(string pEmail) {
SqlCommand command = con.CreateCommand();
command.CommandText = #"SELECT Sifre FROM Kullanici WITH (NOLOCK) WHERE email=#email";
command.Parameters.Add("#email", SqlDbType.VarChar);
command.Parameters["#email"].Value = pEmail;
using (SqlDataReader rd = command.ExecuteReader())
{
rd.Read();
string pass = rd["Sifre"].ToString();
int p = Convert.ToInt32(pass);
return p;
}
}
Try implementing your code in the below format
using(SqlConnection connection = new SqlConnection("connection string"))
{
connection.Open();
using(SqlCommand cmd = new SqlCommand("your sql command", connection))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader != null)
{
while (reader.Read())
{
//do something
}
}
}
}
}
The using statement will ensure disposal of the objects at the end of the using block
try this:
public int SifreGetir(string pEmail) {
SqlConnection con = new SqlConnection("Your connection string here");
con.Open();
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
SqlCommand command = new SqlCommand(#"SELECT Sifre FROM Kullanici WITH (NOLOCK) WHERE email=#email",con);
command.CommandType = CommandType.Text;
command.Parameters.Add("#email", SqlDbType.VarChar).Value = pEmail;
da.Fill(ds);
foreach(DataRow dr in ds.Tables[0].Rows)
{
string pass = dr["Sifre"].ToString();
int p = Convert.ToInt32(pass);
return p;
}
con.Close();
}
You have used Using Keyword for SQL Reader but There is nothing to take care of your command and connection object to dispose them properly. I would suggest to try disposing your Connection and command both objects by Using keyword.
string connString = "Data Source=localhost;Integrated " + "Security=SSPI;Initial Catalog=Northwind;";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new;
cmd.CommandText = "SELECT ID, Name FROM Customers";
conn.Open();
using (SqlDataReader rd = command.ExecuteReader())
{
rd.Read();
string pass = rd["Sifre"].ToString();
int p = Convert.ToInt32(pass);
return p;
}
}
If I have a DbCommand defined to execute something like:
SELECT Column1 FROM Table1
What is the best way to generate a List<String> of the returned records?
No Linq etc. as I am using VS2005.
I think this is what you're looking for.
List<String> columnData = new List<String>();
using(SqlConnection connection = new SqlConnection("conn_string"))
{
connection.Open();
string query = "SELECT Column1 FROM Table1";
using(SqlCommand command = new SqlCommand(query, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
columnData.Add(reader.GetString(0));
}
}
}
}
Not tested, but this should work fine.
Loop through the Items and Add to the Collection. You can use the Add method
List<string>items=new List<string>();
using (var con= new SqlConnection("yourConnectionStringHere")
{
string qry="SELECT Column1 FROM Table1";
var cmd= new SqlCommand(qry, con);
cmd.CommandType = CommandType.Text;
con.Open();
using (SqlDataReader objReader = cmd.ExecuteReader())
{
if (objReader.HasRows)
{
while (objReader.Read())
{
//I would also check for DB.Null here before reading the value.
string item= objReader.GetString(objReader.GetOrdinal("Column1"));
items.Add(item);
}
}
}
}
Or a nested List (okay, the OP was for a single column and this is for multiple columns..):
//Base list is a list of fields, ie a data record
//Enclosing list is then a list of those records, ie the Result set
List<List<String>> ResultSet = new List<List<String>>();
using (SqlConnection connection =
new SqlConnection(connectionString))
{
// Create the Command and Parameter objects.
SqlCommand command = new SqlCommand(qString, connection);
// Create and execute the DataReader..
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
var rec = new List<string>();
for (int i = 0; i <= reader.FieldCount-1; i++) //The mathematical formula for reading the next fields must be <=
{
rec.Add(reader.GetString(i));
}
ResultSet.Add(rec);
}
}
If you would like to query all columns
List<Users> list_users = new List<Users>();
MySqlConnection cn = new MySqlConnection("connection");
MySqlCommand cm = new MySqlCommand("select * from users",cn);
try
{
cn.Open();
MySqlDataReader dr = cm.ExecuteReader();
while (dr.Read())
{
list_users.Add(new Users(dr));
}
}
catch { /* error */ }
finally { cn.Close(); }
The User's constructor would do all the "dr.GetString(i)"
Where the data returned is a string; you could cast to a different data type:
(from DataRow row in dataTable.Rows select row["columnName"].ToString()).ToList();
This version has the same purpose of #Dave Martin but it's cleaner, getting all column, and easy to manipulate the data if you wan't to put it on Email, View, etc.
List<string> ResultSet = new List<string>();
using (SqlConnection connection = DBUtils.GetDBConnection())
{
connection.Open();
string query = "SELECT * FROM DATABASE";
using (SqlCommand command = new SqlCommand(query, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var rec = new List<string>();
for (int i = 0; i <= reader.FieldCount - 1; i++)
{
rec.Add(reader.GetString(i));
}
string combined = string.Join("|", rec);
ResultSet.Add(combined);
}
}
}
}
This bit of code runs on Windows Compact Framework and what it does is obvious. It looks as it should be refactored (especially considering that I may want to add cmd.ExecuteResultSet() later), but I can't see an elegant way to do it. Any ideas appreciated.
internal void RunNonQuery(string query)
{
string connString = GetLocalConnectionString();
using (SqlCeConnection cn = new SqlCeConnection(connString))
{
cn.Open();
SqlCeCommand cmd = cn.CreateCommand();
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
}
internal int RunScalar(string query)
{
string connString = GetLocalConnectionString();
using (SqlCeConnection cn = new SqlCeConnection(connString))
{
cn.Open();
SqlCeCommand cmd = cn.CreateCommand();
cmd.CommandText = query;
return int.Parse(cmd.ExecuteScalar().ToString());
}
}
I'm not sure I would refactor it, but perhaps:
static void PerformQuery(string connectionString, string command,
Action<SqlCeCommand> action)
{ //TODO: sanity checks...
using(SqlCeConnection conn = new SqlCeConnection(connectionString))
using(SqlCeCommand cmd = conn.CreateCommand()) {
cmd.CommandText = command;
conn.Open();
action(cmd);
}
}
internal void RunNonQuery(string query)
{
string connString = GetLocalConnectionString();
PerformQuery(connString, query, cmd => cmd.ExecuteNonQuery());
}
internal int RunScalar(string query)
{
int result = 0;
string connString = GetLocalConnectionString();
PerformQuery(connString, query,
cmd => {result = int.Parse(cmd.ExecuteScalar().ToString()); }
);
return result;
}
Otherwise - just maybe a CreateAndOpenConnection(string) method, and a CreateCommand(SqlCeConnection,string) method.
If you are using C# 3.0, you could do something like the following:
private T CreateCommand<T>(string query, Func<SqlCeCommand, T> func)
{
var connString = GetLocalConnectionString();
using (var cn = new SqlCeConnection(connString))
{
cn.Open();
using (var cmd = cn.CreateCommand())
{
cmd.CommandText = query;
return func(cmd);
}
}
}
private void CreateCommand(string query, Action<SqlCeCommand> action)
{
CreateCommand<object>(query, cmd =>
{
action(cmd);
return null;
});
}
internal void RunNonQuery(string query)
{
CreateCommand(query, cmd => cmd.ExecuteNonQuery());
}
internal int RunScalar(string query)
{
return CreateCommand(query, cmd =>
int.Parse(cmd.ExecuteScalar().ToString()));
}
I would create a class out of the code to wrap the connection creation and command execution logic. This will provide you with a single place to implement transactions in the future and will consolidate creation of the connection and command. This consolidation will allow for settings timeouts, joining transactions, etc.
class Connection : IDisposable
{
readonly SqlConnection _conn;
public Connection()
{
string connString = GetLocalConnectionString();
_conn = new SqlConnection(connString);
_conn.Open();
}
public void Dispose() { _conn.Dispose(); }
public SqlCommand CreateCommand(string qry)
{
SqlCommand cmd = _conn.CreateCommand();
cmd.CommandText = qry;
//cmd.CommandTimeout = TimeSpan.FromMinutes(x);
return cmd;
}
public int ExecuteNonQuery(string qry)
{
using (SqlCommand cmd = CreateCommand(qry))
return cmd.ExecuteNonQuery();
}
public int RunScalar(string qry)
{
using (SqlCommand cmd = CreateCommand(qry))
return int.Parse(cmd.ExecuteScalar().ToString());
}
}
Then if you still want to maintain your original API, you do the following:
class SqlCode
{
internal void RunNonQuery(string query)
{
using (Connection cn = new Connection())
cn.ExecuteNonQuery(query);
}
internal int RunScalar(string query)
{
using (Connection cn = new Connection())
return cn.RunScalar(query);
}
}
The only thing left is to re-insert the 'Ce' in the SqlXxxx stuff ;)