Read data from SQL Server database with c# - sql-server

I have list of BuilderString which I want to contain data
public List<int> IDS = new List<int>();
public List<StringBuilder> Items = new List<StringBuilder>();
What's wrong with this code?
SqlConnection con2 = new SqlConnection("Data Source=aya-PC\\SQLEXPRESS;Initial Catalog=ItemSet;Integrated Security=True");
SqlDataReader rdr2;
SqlCommand cmd2;
con2.Open();
for (int i = 0; i < IDS.Count; i++)
{
cmd2 = new SqlCommand("select item From TransactiontData where idT=#IDS[i]", con2);
cmd2.CommandType = CommandType.Text;
rdr2 = cmd2.ExecuteReader();
SqlParameter param = new SqlParameter();
param.ParameterName = "#IDS[i]"
while (rdr2.Read())
{
Items[i].Append((StringBuilder)rdr2["item"]);
}
}

You need to rearrange your code a bit:
using (SqlConnection con2 = new SqlConnection("Data Source=aya-PC\\SQLEXPRESS;Initial Catalog=ItemSet;Integrated Security=True"))
using (SqlCommand cmd2 = new SqlCommand("select item From TransactiontData where idT = #IDS", con2))
{
// add the paramter to the command
cmd2.Parameter.Add("#IDS", SqlDbType.Int);
con2.Open();
for (int i = 0; i < IDS.Count; i++)
{
// set the parameter value
cmd2.Parameter["#IDS"].Value = IDS[i];
// only *THEN* call ExecuteReader()
using (SqlDataReader rdr2 = cmd2.ExecuteReader())
{
while (rdr2.Read())
{
// **NOT SURE** what you're trying to do here.....
// First of all, you need to just call Items.Add()
// to add new items to the list - and I'm TOTALLY
// UNCLEAR what you're trying to do casting the reader
// value to a StringBuilder.......
//
// Items[i].Append((StringBuilder)rdr2["item"]);
//
// replaced with what *might* make more sense.....
Items.Add(rdr2["item"].ToString());
}
rdr.Close();
}
}
con2.Close();
}
Points to note:
I would recommend to always put your SqlConnection, SqlCommand and SqlDataReader into using() {...} blocks to ensure proper disposal
you need to add your parameter and set its value BEFORE you call .ExecuteReader()!
Since the query itself never changes - there's no point in creating a new SqlCommand on every iteration. Create the command once - and then just set the parameter value (which is the only thing changing) once per iteration

You need to assign the parameter value in the application code rather than within the query. I'm not sure exactly what you are trying to accomplish by casting the column value as a StringBuilder. Assuming that each StringBuilder item is to contain a single string retrieved from a varchar/nvarchar column, the example below will do that.
for (int i = 0; i < IDS.Count; i++)
{
var cmd2 = new SqlCommand("select item From TransactiontData where idT=#IDS", con2);
SqlParameter param = new SqlParameter("#IDS", SqlDbType.Int) { Value = IDS[i] };
var rdr2 = cmd2.ExecuteReader();
while (rdr2.Read())
{
Items.Add(new StringBuilder((string)rdr2["item"]));
}
}

Related

ds.Tables["TableName"] threw an exception "System.Data.DataTableCollection.this[string].get returned null."

I'm working on a Exporting DataGridView to CSV File and I have this problem:
When i try with table name ( ds.Tables["tableName"] ) it threw an exception "System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.Data.DataTableCollection.this[string].get returned null.
"
but it is working with the index of table: ds.Tables[0].
In my case I have only the names of the table.
I've tried with ds.Tables["dbo.tableName"] also ds.Tables[(row.Cells["table_name"].Value.ToString())]
this is my code:
{
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
foreach (DataGridViewRow row in TableNamesGrid.Rows)
{
bool isSelected = Convert.ToBoolean(row.Cells["CheckBox"].Value);
if (isSelected)
{
StringBuilder stringBuilder = new StringBuilder();
SqlDataAdapter sqlData = new SqlDataAdapter("SELECT * FROM " + row.Cells[1].Value, sqlConnection);
DataSet ds = new DataSet();
sqlData.Fill(ds);
foreach (DataRow dataRow in ds.Tables[(row.Cells["table_name"].Value.ToString())].Rows)
{
for (int i = 0; i <= ds.Tables[(row.Cells["table_name"].Value.ToString())].Rows.Count; i++)
{
stringBuilder.Append(dataRow[i].ToString() + ",");
}
stringBuilder.Append("\r\n");
}
StreamWriter file = new StreamWriter(#"D:\Projects\AlatiWF\data.csv");
file.WriteLine(stringBuilder.ToString());
file.Close();
}
}
}
}
The SqlDataAdapter is not smart enough to work out that your query is just accessing a single table, so it will always return tables named like this: "Table0", "Table1", "Table2", etc.
Table[0] works because it's accessing the table called "Table0". You can give the tables sensible names after your call to sqlData.Fill(ds) by doing something like:
ds.Tables[0].TableName = "SensibleTableName";
Directly fill the Datatable and without Dataset.
DataTable dt = new DataTable();
sqlData.Fill(dt);
foreach (DataRow dataRow in dt.Rows)
{

Save list of Arabic strings in database

I have a c# program. I have list of string. The elements of that list in Arabic. When I try to save the elements of list in database I see symbols "??????"
Here my code
List<string> _names = new List<string>()
{
"ذهب",
"قال",
"تعال",
"متى",
"البرمجة",
"احمد"
};
SqlConnection connection = new SqlConnection("Server=DESKTOP-JRS3DQ4; DataBase=Library_DB; Integrated Security=true");
connection.Open();
for (int index = 0; index < _names.Count; index++)
{
SqlCommand command = new SqlCommand("INSERT INTO tbl_names (id,name) VALUES ('" + index + "', '" + _names[index] + "')", connection);
command.ExecuteNonQuery();
}
connection.Close();
How I can solve this problem please?
Most likely, your problem is coming from inserting strings (as varchar) instead of NVarchar.
Your code will work more-reliably, safer & faster if you define a parameterized query and parameters before you run your loop:
List<string> _names = new List<string>()
{
"ذهب",
"قال",
"تعال",
"متى",
"البرمجة",
"احمد"
};
SqlConnection connection = new SqlConnection("Server=DESKTOP-JRS3DQ4; DataBase=Library_DB; Integrated Security=true");
connection.Open();
SqlCommand command = new SqlCommand("INSERT INTO tbl_names (id,name) VALUES (#Id, #Name)", connection);
command.Parameters.Add("#Id", SqlDbType.Int);
command.Parameters.Add("#Name", SqlDbType.NVarChar, 20); //size and type must match your DB
for (int index = 0; index < _names.Count; index++)
{
command.Parameters["#Id"].Value = index;
command.Parameters["#Name"].Value = _names[index];
command.ExecuteNonQuery();
}
connection.Close();
One last note: This will not help unless your DB has the Name column defined as a NVarChar.

How to get list of all database from NpgsqlConnection in a combobox using c#.net

Im trying to develop a console application and i need to know the all database list name .but this code is not working .This is my code:
public static List<string> AllNpgsqlDatabaseName()
{
List<string> li = new List<string>();
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Username=root;Password=root;");
connection.Open();
NpgsqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT name from sys.databases";
NpgsqlDataReader Reader;
Reader = command.ExecuteReader();
while (Reader.Read())
{
string row = "";
for (int i = 0; i < Reader.FieldCount; i++)
row += Reader.GetValue(i).ToString() + ", ";
li.Add(row);
}
connection.Close();
return li;
}
You can run
SELECT datname FROM pg_database

Stored Procedure returns a temporary table that I need to convert to a CSV file

I basically have a stored procedure that I call through a method:
Time_Tracker.BLL.ResultsManager.GetCSV(Convert.ToDateTime("2014-01-11"));
It returns 8 columns of data ranging from 25 to 150 records.
I need to be able to convert it to a CSV file to a path of the users choosing. I am able to get it into my code behind as an array ( Results[] TEST = new Results[25]; ) and have verified that the data is O.K. I see plenty of posts were they use a DataTable as a source to convert to CSV, but I am not sure how to load a DataTable from the method that calls the stored procedure. Same thing with DataGridView, not sure how to load the data into a DataGridView either.
I have also seen methods were they use SqlDataAdapter to populate a DataTable. Since I use methods to that work directly with stored procedures, I don't want to have to use SqlDataAdapter and provide the database configuration info each time.
IF someone could help me load it into a DataTable or DataGridView, I think I can figure it out from there.
Thank you in advance.
Eric
Just define a data table and use the load command to move the data from the reader to the data table.
http://msdn.microsoft.com/en-us/library/d7125bke.aspx
This is right from MSDN. I added two lines to load a data table.
-- Code from msdn
SqlConnection sqlConnection1 = new SqlConnection("Your Connection String");
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "StoredProcedureName";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
SqlDataReader reader = cmd.ExecuteReader();
-- This is my addition
DataTable dt = new DataTable();
dt.Load(reader);
sqlConnection1.Close();
I still do not understand what you are trying to do. You can create a data table, xml record set, via coding.
The code below can be used to translate an array to a DataTable. Some work is needed on your side to add your details.
http://msdn.microsoft.com/en-us/library/skef0k7a(v=vs.110).aspx
// Create sample Customers table.
DataTable table = new DataTable();
table.TableName = "Customers";
// Create two columns, ID and Name.
DataColumn idColumn = table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));
// Set the ID column as the primary key column.
table.PrimaryKey = new DataColumn[] { idColumn };
table.Rows.Add(new object[] { 0, "Mary" });
table.Rows.Add(new object[] { 1, "Andy" });
table.Rows.Add(new object[] { 2, "Peter" });
table.AcceptChanges();
return table;
I hope this helps. If not, I still do not get the business requirement.
I figured it out (See Below). I will mark this as solved and once again, Thank You for your help !
foreach (DataRow dr in dt.Rows)
{
for (int i = 0; i < iColCount; i++)
{
if (!Convert.IsDBNull(dr[i]))
{
if (dr[i] is DateTime)
{
if (((DateTime)dr[i]).TimeOfDay.TotalSeconds == 0) // Time Since Midnight (in Seconds)
{
sw.Write(((DateTime)dr[i]).ToString("yyyy-MM-dd"));
}
}
else
{
sw.Write(dr[i].ToString());
}
}
if (i < iColCount - 1) sw.Write(",");
}
sw.Write(sw.NewLine);
}
Here is what I ended up doing for anyone else looking for help:
protected void btnCSV_Click(object sender, EventArgs e)
{
try
{
// HATE EXPOSING THE DATABASE CONNECTION THIS WAY !!!
SqlConnection sqlConnection1 = new SqlConnection(DAL.DBUtils.SqlConnectionString);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "[dbo].[usp.CSV_OUT]";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#DateBeg", Time_Tracker.Utilities.TimeCard_Start_Date());
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
SqlDataReader reader = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
sqlConnection1.Close();
ExportToCSV(dt, ConfigurationManager.AppSettings["CSVPath"].ToString(), "CSV_Hours_Data_" + Time_Tracker.Utilities.TimeCard_Start_Date().AddDays(+6).ToString("MM_dd_yyyy") + ".csv");
}
catch (Exception ex)
{
Utilities.ErrorLog(ex.Message, ex.GetType().ToString(), ex.StackTrace, #"Time_Tracker.txt");
}
}
public static void ExportToCSV(DataTable dt, string strFilePath, string fileName)
{
try
{
var sw = new StreamWriter(strFilePath + fileName, false);
// Write the headers.
int iColCount = dt.Columns.Count;
for (int i = 0; i < iColCount; i++)
{
sw.Write(dt.Columns[i]);
if (i < iColCount - 1) sw.Write(",");
}
sw.Write(sw.NewLine);
// Write rows.
foreach (DataRow dr in dt.Rows)
{
for (int i = 0; i < iColCount; i++)
{
if (!Convert.IsDBNull(dr[i]))
{
string output = dr[i].ToString();
if (dr[i] is DateTime)
{
if (((DateTime)dr[i]).TimeOfDay.TotalSeconds == 0) // Time Since Midnight (in Seconds)
{
output = (((DateTime)dr[i]).ToString("yyyy-MM-dd"));
}
}
if (output.Contains(";") || output.Contains("\""))
output = '"' + output.Replace("\"", "\"\"") + '"';
if (Regex.IsMatch(output, #"(?:\r\n|\n|\r)"))
output = string.Join(" ", Regex.Split(output, #"(?:\r\n|\n|\r)"));
sw.Write(output);
}
if (i < iColCount - 1) sw.Write(",");
}
sw.Write(sw.NewLine);
}
sw.Close();
// Causes Save As Dialog box to appear for user.
String FileName = fileName;
String FilePath = strFilePath;
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath + FileName);
response.Flush();
response.End();
}
catch (Exception ex)
{
Utilities.ErrorLog(ex.Message, ex.GetType().ToString(), ex.StackTrace, #"Time_Tracker.txt");
}
}

Hitting "COM object that has been separated from its underlying RCW cannot be used" error

I am trying to write a Windows Form program on top of .NET 4.0 and accessing Microsoft Access Database. I can read and write with no problem but sometimes, I get this error:
COM object that has been separated from its underlying RCW cannot be used.
I tried to call this method (GetIDBasedonTeamName) with different inputs twice (on the same thread). The second time this is run, I got that error.
OleDbConnection conn = new OleDbConnection();
OleDbConnection mDB = new OleDbConnection();
OleDbCommand comm = new OleDbCommand();
OleDbCommand cmd;
OleDbDataReader dr;
public void OpenConnection(string name) // always call this method first in other methods to initialise connection
{
conn.ConnectionString = "Provider = Microsoft.Jet.OLEDB.4.0;Data source="
+ Application.StartupPath + "\\AppData\\" + name + ".mdb;";
conn.Open();
comm.Connection = conn;
comm.Parameters.Clear();
}
public string GetIDBasedonTeamName(string teamName)
{
string toReturn = "";
try
{
OpenConnection("form");
comm.CommandText = "Select ID from TeamDetails WHERE TeamName=#teamName";
comm.Parameters.AddWithValue("TeamName", teamName);
dr = comm.ExecuteReader();
while (dr.Read())
{
toReturn = dr[0].ToString();
}
}
catch (OleDbException e)
{
string err = e.Message.ToString();
return null;
}
finally
{
}
conn.Close();
dr.Close();
return toReturn;
}
Exception happened on dr = comm.ExecuteReader();.
The method that was calling this method have this 2 lines inside:
InfoConfig.team1id = Convert.ToInt32(dbm.GetIDBasedonTeamName(cbxTeam1.Text));
InfoConfig.team2id = Convert.ToInt32(dbm.GetIDBasedonTeamName(cbxTeam2.Text));
What could be the cause? I read around and they mentioned not to use different threads but it is the same thread here.
Thanks,
Guo Hong
Building on Martin Liversage's answer:
public string GetIDBasedonTeamName(string teamName) {
var connString = "Provider = Microsoft.Jet.OLEDB.4.0;Data source="
+ Application.StartupPath + "\\AppData\\" + name + ".mdb;";
using (var conn = new OleDbConnection(connString)) {
conn.Open();
using (var cmd = conn.CreateCommand()) {
cmd.CommandText="Select ID from TeamDetails WHERE TeamName = #teamName";
cmd.Parameters.AddWithValue("TeamName", teamName);
using (var rdr = cmd.ExecuteReader()) {
if (rdr.Read()) {
return (string)rdr["TeamName"];
}
//if no valid results will return null
}
}
}
}
Instead of creating the objects only once and storing them in fields in your class you should create, use and close the objects in your method. It is probably the Close you call in the end the method that releases the underlying COM objects giving you the exception on the second call.

Resources