I want to print the output of the stored procedure in a .csv file.
When I insert a single stored procedure such as exec spGet Table 5 1,null,null,null,111,null,null,null,61,null,null,3;
Along with its parameters it executes. But when I pass the same procedure multiple times with different parameters, It only executes the first Stored procedure and the remaining are ignored. In the CSV file i only get the first SP Output.
My code is as follows
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnGetSku_Click(object sender, EventArgs e)
{
Stopwatch swra = new Stopwatch();
swra.Start();
StreamWriter CsvfileWriter = new StreamWriter(#"D:\testfile.csv");
string connectionString = null;
SqlConnection cnn;
connectionString = "Data Source=My-PC-Name;Initial Catalog=MyDB;User
cnn = new SqlConnection(connectionString);
ID=Name;Password=********";
cnn.Open();
SqlCommand cmd = new SqlCommand(textBox1.Text, cnn);
cmd.CommandText = textBox1.Text;
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 2000;
using (cnn)
{
using (SqlDataReader rdr = cmd.ExecuteReader())
using (CsvfileWriter)
{
//For getting the Table Headers
DataTable Tablecolumns = new DataTable();
for (int i = 0; i < rdr.FieldCount; i++)
{
Tablecolumns.Columns.Add(rdr.GetName(i));
}
CsvfileWriter.WriteLine(string.Join(",",
Tablecolumns.Columns.Cast<DataColumn>().Select(csvfile =>
csvfile.ColumnName)));
while (rdr.Read())
{
label1.Text = rdr["SKU"].ToString() + " " +
rdr["SKUCode"].ToString();
CsvfileWriter.WriteLine(rdr["SKU"].ToString() + "," +
rdr["SKUCode"].ToString() + "," +
rdr["Compliance_Curr"].ToString() + "," +
rdr["Compliance_Prev"].ToString() + "," +
rdr["Difference"].ToString() + "," +
rdr["TotalSales_Curr"].ToString() + ",");
}
cnn.Close();
}
}
swra.Stop();
Console.WriteLine(swra.ElapsedMilliseconds);
}
}
I want to make sure that each procedure is executed differently and appended to the .csv file.
The problem you are facing is due to overwriting the file each time. So what you have in there is actually the result of the last execution of the command.
The culprit is the following line:
StreamWriter CsvfileWriter = new StreamWriter(#"D:\testfile.csv");
According to documentation,
If the file exists, it is overwritten; otherwise, a new file is created.
You need to use an overload of StreamWriter constructor which accepts a bool value specifying whether to append to the file or overwrite it.
var csvFileWriter = new StreamWriter(#"D:\testfile.csv", true);
Have you tried to call stored procedure with names of parameters (which declared in stored procedure)?
For example: EXECUTE spGet #Id = 1, #Number = 111, #....
In your code, you are creating StreamWriter object **everytime, you are clicking on **btnGetSku, Try to make it member variable and then write. Data is not being appended,
StreamWriter CsvfileWriter = null;
private void btnGetSku_Click(object sender, EventArgs e)
{
Stopwatch swra = new Stopwatch();
swra.Start();
if(CsvfileWriter == null)
CsvfileWriter = new StreamWriter(#"D:\testfile.csv");
string connectionString = null;
SqlConnection cnn;
connectionString = "Data Source=My-PC-Name;Initial Catalog=MyDB;User
cnn = new SqlConnection(connectionString);
ID=Name;Password=********";
cnn.Open();
SqlCommand cmd = new SqlCommand(textBox1.Text, cnn);
cmd.CommandText = textBox1.Text;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 2000;
using (cnn)
{
using (SqlDataReader rdr = cmd.ExecuteReader())
// Don't use using here. This disposes the streams
//using (CsvfileWriter)
{
//For getting the Table Headers
DataTable Tablecolumns = new DataTable();
for (int i = 0; i < rdr.FieldCount; i++)
{
Tablecolumns.Columns.Add(rdr.GetName(i));
}
CsvfileWriter.WriteLine(string.Join(",",
Tablecolumns.Columns.Cast<DataColumn>().Select(csvfile =>
csvfile.ColumnName)));
while (rdr.Read())
{
label1.Text = rdr["SKU"].ToString() + " " +
rdr["SKUCode"].ToString();
CsvfileWriter.WriteLine(rdr["SKU"].ToString() + "," +
rdr["SKUCode"].ToString() + "," +
rdr["Compliance_Curr"].ToString() + "," +
rdr["Compliance_Prev"].ToString() + "," +
rdr["Difference"].ToString() + "," +
rdr["TotalSales_Curr"].ToString() + ",");
}
cnn.Close();
}
}
swra.Stop();
Console.WriteLine(swra.ElapsedMilliseconds);
}
Related
Okay, so i'm trying to get 18 "prices" from my database in SQL, then setting them in a local array. So far i have this logic in the data retrieval:
private void dbPrices()
{
string myConnectionString;
myConnectionString = "server=127.0.0.1;uid=root;" +
"pwd=;database=phvpos";
try
{
conn = new MySql.Data.MySqlClient.MySqlConnection();
conn.ConnectionString = myConnectionString;
conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message);
}
for (int i = 1; i < 19; i++)
{
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT price from products where id = '" + i + "'";
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
pr[i] = reader.ToString();
prods[i] = int.Parse(pr[i]);
}
}
}
And this logic in getting the total amount:
private void btnTotal_Click(object sender, EventArgs e)
{
dbPrices();
itemcost[0] = Convert.ToInt32(txtRice.Text) * prods[0];
itemcost[1] = Convert.ToInt32(txtAdobo.Text) * prods[1];
itemcost[2] = Convert.ToInt32(txtIgado.Text) * prods[2];
itemcost[3] = Convert.ToInt32(txtSisig.Text) * prods[3];
...
itemcost[18] = itemcost[0] + itemcost[1] + itemcost[2] + itemcost[3] + itemcost[4] + itemcost[5]
+ itemcost[6] + itemcost[7] + itemcost[8] + itemcost[9] + itemcost[10]
+ itemcost[11] + itemcost[12] + itemcost[13] + itemcost[14] + itemcost[15]
+ itemcost[16] + itemcost[17];
int totalPrice = itemcost[18];
lblTotal.Text = Convert.ToString(totalPrice);
}
this line in dbPrices() spits out a 'input string was not in a correct format' error:
while (reader.Read())
{
pr[i] = reader.ToString();
prods[i] = int.Parse(pr[i]);
}
I have also tried:
while (reader.Read())
{
prods[i] = Convert.toInt32(reader.ToString());
}
But also spits the same error. Is there anything that i'm doing wrong?
Try this. I find that when using 'reader' that even when your query only grabs one value you still need to specify what value your looking for.
prods[i] = int.Parse(reader["price"]);
and if price is nullable in the database use a ternary operator
prods[i] = reader["price"] == DBNull.Value ? 0 : int.parse(reader["price"]);
The value from your result needs to convert to int and your for loop block might cause you serious problem in the future, you might want to have a projection query and then assign the values of the result.
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = $"SELECT price FROM products WHERE id BETWEEN 1 AND 18"; //use projection. if you have a dynamic product id set, you can use IN in query.
MySqlDataReader reader = cmd.ExecuteReader();
var counter = 0; //counter
while (reader.Read())
{
prods[counter] = Convert.ToInt32(reader["price"]); //convert the result first then assign it to the item.
counter++;
}
I have a datagridview which is created by various action and user's manipulation of data. I want to insert all the data of the gridview to the database at once, I know I could try a code similar to this:
private void btnSaveProducts_Click(object sender, EventArgs e)
{
SqlConnection connection = DBConnectivity.getConnection();
if (connection != null)
{
try
{
for (int i = 0; i < dGvProducts.Rows.Count; i++)
{
string query = "INSERT INTO product (productName) " + "VALUES (#productName)";
SqlCommand command = DBConnectivity.getCommandForQuery(query, connection);
int result = command.ExecuteNonQuery();
Console.WriteLine(result + "");
}
// string query = "Insert into units(name,packing)values('" + txtNameUnit.Text + "' , '" + txtPackingUnit.Text + "')";
// SqlCommand command = DBConnectivity.getCommandForQuery(query, connection);
// int result = command.ExecuteNonQuery();
// Console.WriteLine(result + "");
}
catch (Exception ex)
{
}
finally
{
connection.Close();
}
}
}
As is, the code tries to execute a parameterized query but never assigns a value to the parameter. Even if you do, you never extract the cell values.
The code should look like this:
var query = "INSERT INTO product (productName) VALUES (#productName)";
using var(connection = DBConnectivity.getConnection())
using(var command = new SqlCommand(query, connection))
{
var productParam=command.Parameters.Add("#productName",SqlDbType.NVarChar,50);
connection.Open();
for (int i = 0; i < dGvProducts.Rows.Count; i++)
{
var productName=dGvProducts.Rows[i].Cells[somecolumn].Value;
productParam.Value=productName;
int result = command.ExecuteNonQuery();
Console.WriteLine(result);
}
}
My question, which is similar to this one, is how can I use OracleDataReader to retrieve all the fields for a given record? Currently, I've been using this method, which returns only one column value at a time:
public string Select_File(string filename, string subdirectory, string envID)
{
Data_Access da = new Data_Access();
OracleConnection conn = da.openDB();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename ='" + filename + "'"
+ " AND Subdirectory = '" + subdirectory + "'"
+ " AND Environment_ID = '" + envID + "'";
cmd.CommandType = CommandType.Text;
string x;
OracleDataReader dr = cmd.ExecuteReader();
if (dr.HasRows) // file exists in DB
{
dr.Read();
x = dr.GetString(2).ToString(); // return baseline filename (index 2)
}
else
{
x = "New File";
}
cmd.Dispose();
da.CloseDB(conn);
return x;
}
I'm sure that this method is far from perfect and ppl will be quick to point that out (I was basically given it by my supervisor since I didn't have any prior experience in ASP.NET) but all I really care about is that it works. My question is: how can it be modified to return all the fields for a given record?
The fields will be of either VARCHAR2, CHAR, or DATE datatypes, (if that makes a difference) and some of these values may be null. I'm thinking I could convert them to strings and return them as a list?
if u want something like this:
List<User> lstUser = new List<User>();
string sqlQuery = "Select * from User_T where User_Name='" + oUser.UserName + "' And Password='" +oUser.Password + "' AND IsActive='"+1+"' AND IsDelete='"+0+"'";
string connectionString = "Data Source=ORCL;User Id=ACCOUNTS;Password=ACCOUNTS";
using (DBManager dbManager = new DBManager(connectionString))
{
try
{
dbManager.Open();
OracleDataReader dataReader = dbManager.ExecuteDataReader(sqlQuery);
while (dataReader.Read())
{
oUser = new User();
oUser.Id = Convert.ToInt32(dataReader["ID"]);
oUser.CompanyId = Convert.ToInt32(dataReader["Company_ID"]);
oUser.BranchId = Convert.ToInt32(dataReader["Branch_ID"]);
oUser.UserName = Convert.ToString(dataReader["User_Name"]);
lstUser.Add(oUser);
}
dataReader.Close();
dataReader.Dispose();
}
catch
(Exception)
{
}
finally
{
dbManager.Close();
dbManager.Dispose();
}
To read all the data from the columns of the current row in a DataReader, you can simply use GetValues(), and extract the values from the array - they will be Objects, of database types.
Object[] values;
int numColumns = dr.GetValues(values); //after "reading" a row
for (int i = 0; i < numColumns; i++) {
//read values[i]
}
MSDN - "For most applications, the GetValues method provides an efficient means for retrieving all columns, rather than retrieving each column individually."
Sorry for posting an answer to a very old question. As none of the answers are correct (either they have security issues or not checking for DBNull), I have decided to post my own.
public async Task<StringBuilder> FetchFileDetailsAsync(string filename, string subdirectory, string envId)
{
var sb = new StringBuilder();
//TODO: Check the parameters
const string connectionString = "user id=userid;password=secret;data source=" +
"(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.8)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=xe)))";
const string selectQuery = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename = :filename"
+ " AND Subdirectory = :subdirectory"
+ " AND Environment_ID = :envID"
+ " AND rownum<=1";
using (var connection = new OracleConnection(connectionString))
using (var cmd = new OracleCommand(selectQuery, connection) {BindByName = true, FetchSize = 1 /*As we are expecting only one record*/})
{
cmd.Parameters.Add(":filename", OracleDbType.Varchar2).Value = filename;
cmd.Parameters.Add(":subdirectory", OracleDbType.Varchar2).Value = subdirectory;
cmd.Parameters.Add(":envID", OracleDbType.Varchar2).Value = envId;
//TODO: Add Exception Handling
await connection.OpenAsync();
var dataReader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection);
var rowValues = new object[dataReader.FieldCount];
if (dataReader.Read())
{
dataReader.GetValues(rowValues);
for (var keyValueCounter = 0; keyValueCounter < rowValues.Length; keyValueCounter++)
{
sb.AppendFormat("{0}:{1}", dataReader.GetName(keyValueCounter),
rowValues[keyValueCounter] is DBNull ? string.Empty : rowValues[keyValueCounter])
.AppendLine();
}
}
else
{
//No records found, do something here
}
dataReader.Close();
dataReader.Dispose();
}
return sb;
}
I retrieve data from Oracle database and populate a gridview. Next, I try to run a query to select some data but I get an error.
Here is the code:
Db.cs:
public static OracleConnection GetConnection()
{
OracleConnection connection = null;
string connectionString = "Data Source=" + Database +
";User ID=" + UserID +
";Password=" + Password +
";Unicode=True";
try
{
connection = new OracleConnection(connectionString);
}
catch (OracleException ex)
{
throw ex;
}
return connection;
}
Parameters are sent from default.aspx.cs:
new Db(database, userID, password);
OracleConnection connection = Db.GetConnection();
main.aspx.cs retrieves all the data:
private OracleConnection connection = new OracleConnection();
private Select select = new Select();
protected void Page_Load(object sender, EventArgs e)
{
Response.Buffer = true;
if (Db.IsLoggedIn())
{
string selectCommand =
"SELECT " + Settings.TABLE + ".* FROM " + Settings.TABLE + " ORDER BY ";
foreach (string ob in Settings.OB) selectCommand += ob + ", ";
Session["Error"] = null;
connection = Db.GetConnection();
select = new Select(ddlBubID, ddlBusArea, ddlDrillSite, ddlWell, connection);
gvData.DataKeyNames = Settings.PK;
gvData.SelectedIndex = -1;
DS.ConnectionString = connection.ConnectionString;
DS.SelectCommand = selectCommand.Remove(selectCommand.Length - 2, 2);
DS.ProviderName = Settings.PROVIDER_NAME;
PopulateFooter(gvData.FooterRow);
}
else
{
Session["Error"] = Settings.ERROR_MESSAGE[0, 0];
Response.Clear();
Response.Redirect("default.aspx");
}
}
public string ToolTip(string column)
{
string value = "";
OracleCommand cmd = new OracleCommand();
cmd.Connection = connection;
cmd.CommandText = "SELECT DISTINCT COMMENTS " +
"FROM SYS.ALL_COL_COMMENTS " +
"WHERE (TABLE_NAME = 'CTD_PROBLEM_EDIT_V') " +
"AND (COLUMN_NAME = " + column + ")";
cmd.CommandType = CommandType.Text;
OracleDataReader reader = cmd.ExecuteReader(); // I get an error here
reader.Read();
value = reader["COMMENTS"].ToString();
reader.Close();
return value;
}
protected void gvData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
for (int i = 1; i < e.Row.Cells.Count; i++)
{
try
{
LinkButton lb =
(LinkButton)gvData.HeaderRow.Cells[i].Controls[0];
lb.ToolTip = ToolTip(lb.Text);
/* Blah Blah*/
}
catch { }
}
if (e.Row.RowType == DataControlRowType.Footer)
PopulateFooter(e.Row);
}
ToolTip(); throws an error:
Invalid operation. The connection is closed.
EDIT:
This would have been helpful:
Static Classes and Static Class Members
Might not be the problem but this looks weird:
new Db(database, userID, password);
OracleConnection connection = Db.GetConnection();
GetConnection is a static method and thus it does not see any member attributes you might be setting in the constructor (unless they are static as well). If they are all static, consider refactoring your code to use the singleton pattern as it is more readable.
Another thing is that the connection attribute is a member of the page class which is generated for each request (not per application). This means you need either create a new connection in ToolTip method (and any other method that accesses the database) or make the connection attribute static to make it per-application.
Try 2 things:
1.. For your ToolTip() method, the value column to compare for COLUMN_NAME will need to be wrapped properly with single quotes indicating a string/varchar literal value. Likely it's evaluating to COLUMN_NAME = foo when it should be COLUMN_NAME = 'foo'.
cmd.CommandText = "SELECT DISTINCT COMMENTS " +
"FROM SYS.ALL_COL_COMMENTS " +
"WHERE (TABLE_NAME = 'CTD_PROBLEM_EDIT_V') " +
"AND (COLUMN_NAME = '" + column + "')";
2.. Try wrapping your ad-hoc SQL statements in BEGIN and END
3.. Consider refactoring your string building for your SELECT and dynamic ORDER BY clause. That you're doing it on the SelectCommand many lines below isn't obvious to the casual observer or maintainers later in its life.
string selectCommand = string.Format("SELECT {0}.* FROM {0} ORDER BY {1}"
,Settings.TABLE
,string.Join(",",Settings.OB));
i face the following problem::
i wanna to escape the following character ' single quote:
it works when making this test through :the built in method Replace("'","''");
as this code below :(just a test) it works
protected void btn_insert_Click(object sender, EventArgs e)
{
lbl.Text = string.Empty;
SqlConnection mycon = new SqlConnection(Constr);`
SqlCommand mycommand = new SqlCommand("INSERT INTO details VALUES('" + txt.Text.Replace("'", "''") + "','" + txt.Text.Replace("'", "''")+ "')", mycon);
mycon.Open();
int affectedRows = 0;
affectedRows = mycommand.ExecuteNonQuery();
mycon.Close();
}
but i wanna to generalize my solution to work all over the application through my Insert method in the data access layer:
public static int InsertEntity(string tblName, Dictionary<string, string> dtParams)
{
int Result = -1;
DBConnection DAL_Helper = new DBConnection("");
string[] field_names = new string[dtParams.Count];
dtParams.Keys.CopyTo(field_names, 0);
string[] field_values = new string[dtParams.Count];
dtParams.Values.CopyTo(field_values, 0);
for (int i = 0; i < field_values.Length; i++)
{
field_values[i].Replace("'", "''");
}
string insertCmd = "INSERT INTO " + tblName + " (" + string.Join(",", field_names) + ") values ('" + string.Join("','", field_values) + "')";
Result = DAL_Helper.Execute_NonQuery(insertCmd);
return Result;
}
this not escaping the ' single quote charecter,although i use Replace("'","''");
what is the problem ,,how to fix this problem?
I strongly recommend you use Command Parameters using SqlCommand.Parameters collection instead of your approach.
Problem is here :
for (int i = 0; i < field_values.Length; i++)
{
field_values[i].Replace("'", "''");
}
Replace it with :
for (int i = 0; i < field_values.Length; i++)
{
field_values[i] = field_values[i].Replace("'", "''");
}
Building on decyclone's answer. CommandParameters are the way to go here, you are just re-inventing it with your own code.
I have found a very nice clear example here for supplying params to a SQL statement.
http://dotnetperls.com/sqlparameter
using (SqlCommand command = new SqlCommand("SELECT * FROM Dogs1 WHERE Name LIKE #Name", connection))
{
string dogName = "Mc'Dougal";
//
// Add new SqlParameter to the command.
//
command.Parameters.Add(new SqlParameter("Name", dogName));
//
// Read in the SELECT results.
//
SqlDataReader reader = command.ExecuteReader();
}