How to resolve key not found exception in dictionary collection - sql

I am trying to store details present in a dictionary into SQL Server using ado.net connection, but I get a key not found exception when I try to insert values into the database.
if(option==2)
{
SqlConnection con = new SqlConnection("Data Source=.;Database=Demo;Integrated Security=SSPI");
con.Open();
SqlCommand cmd = new SqlCommand("INSERT INTO tnlFourWheeler(Vno, years, cost,color,fuel,doors,seats) " +
" VALUES (#Vno, #years, #cost,#color,#fuel,#doors,#seats)", con);
for (int i = 0; i < keyValuePairs.Count; i++)
{
FourWheeler t = (FourWheeler)keyValuePairs[i];
cmd.Parameters.AddWithValue("#Vno", t.vehicleNumber);
cmd.Parameters.AddWithValue("#years", t.numberOfYears);
cmd.Parameters.AddWithValue("#cost", t.cost);
cmd.Parameters.AddWithValue("#color", t.color);
cmd.Parameters.AddWithValue("#fuel", t.fuelType);
cmd.Parameters.AddWithValue("#doors", t.doors);
cmd.Parameters.AddWithValue("#seats", t.seats);
cmd.ExecuteNonQuery();
}
con.Close();

Dictionary<TKey,TValue> is not indexed by array-index, it's indexed by key.
Do this instead (replace TKey with your actual TKey):
foreach( KeyValuePair<TKey,FourWheeler> kvp in keyValuePairs )
{
FourWheeler t = kvp.Value;
// ...
}
Or:
foreach( TKey key in keyValuePairs.Keys )
{
FourWheeler t = keyValuePairs[key];
// ...
}

Related

Is it possible to return an array of dictionaries?

I wrote a function that will return a single sql record as a dictionary. Is it possible to return an array of dictionaries so I can return multiple records in this way?
public static async Task<Dictionary<string, string>> SQLMultiRecordToDictionary(string TableName, string SearchField, string SearchValue)
{
Dictionary<string, string> QueryResult = new Dictionary<string, string>();
// is TableName sane
if (!IsTextSane(TableName)) { return QueryResult; }
//
await using (var connection = new SqliteConnection("Data Source=" + dbFullPathName))
{
connection.Open();
SqliteCommand sqlcmd = connection.CreateCommand();
sqlcmd.CommandText = "SELECT * FROM " + TableName + " WHERE " + SearchField + "=#SearchValue";
sqlcmd.Parameters.AddWithValue("#SearchValue", SearchValue);
SqliteDataReader sqlreader = sqlcmd.ExecuteReader();
// generate dictionary keys with blank values
// this prevents key not existing issues when no record is returned
// i prefer no/blank values in the keys when no record returned for this project
for (int i = 0; i < sqlreader.FieldCount; i++)
{
QueryResult.Add(sqlreader.GetName(i), ""); // blank value
}
// add the values to the keys
while (sqlreader.Read())
{
for (int i = 0; i <= sqlreader.FieldCount - 1; i++)
{
QueryResult[sqlreader.GetName(i)] = sqlreader.GetString(i);
}
}
return QueryResult;
}
}
The working end result thanks to Tisa:
public static async Task<List<Dictionary<string, string>>> SQLMultiRecordToDictionaryList(string TableName, string SearchField, string SearchValue)
{
List<Dictionary<string, string>> QueryResult = new List<Dictionary<string, string>>();
Dictionary<string, string> SQLRecord = new Dictionary<string, string>();
//
// is TableName sane, if not return nothing
if (!IsTextSane(TableName)) { return QueryResult; }
//
await using (var connection = new SqliteConnection("Data Source=" + dbFullPathName))
{
connection.Open();
SqliteCommand sqlcmd = connection.CreateCommand();
sqlcmd.CommandText = "SELECT * FROM " + TableName + " WHERE " + SearchField + "=#SearchValue";
sqlcmd.Parameters.AddWithValue("#SearchValue", SearchValue);
SqliteDataReader sqlreader = sqlcmd.ExecuteReader();
// generate dictionary keys with blank values if no rows
// this prevents key not existing issues when no record is returned
// i prefer no/blank values in the keys when no record returned for this project
if (!sqlreader.HasRows)
{
for (int i = 0; i < sqlreader.FieldCount; i++)
{
SQLRecord.Add(sqlreader.GetName(i), ""); // blank value
}
QueryResult.Add(SQLRecord);
}
//
// add the values to the keys if there are rows (this doesn't run if no rows returned)
while (sqlreader.Read())
{
SQLRecord = new Dictionary<string, string>();
for (int i = 0; i <= sqlreader.FieldCount - 1; i++)
{
SQLRecord.Add(sqlreader.GetName(i), sqlreader.GetString(i));
}
QueryResult.Add(SQLRecord);
}
return QueryResult;
}
}

.NET Query with list as sql parameter

public SqlDataReader GetDataReader(List<SqlParameter> parameterValues){
System.Data.SqlClient.SqlConnection cn = new System.Data.SqlClient.SqlConnection();
cn.ConnectionString = SQLConnectionObj.ConnectionString;
cn.Open();
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
cmd.Parameters.AddRange(parameterValues.ToArray());
cmd.Connection = cn;
cmd.CommandText = SelectStatement;
cmd.CommandType = CommandType.Text;
return sReader = cmd.ExecuteReader();
}
When I try to add this for IN condition variable in select query,it fails.
Need to use this only for Fortify fix.Tried with dictionary Sql parameter.It works but increases the issue count up.
Please help me with this.And also if there is anything new which you want to add feel free to add those too.
But the following code works:-
public SqlDataReader GetDataReader(Dictionary<string, string> qParams)
{
SqlCommand SQLCommandObj = new SqlCommand(SelectStatement,
SQLConnectionObj);
string query=SelectStatement;
if (qParams.Count > 0)
{
foreach (string key in qParams.Keys)
{
string value = qParams[key];
SqlParameter par = new SqlParameter();
par.ParameterName = key;
par.Value = value;
SQLCommandObj.Parameters.Add(par);
}
}
foreach(SqlParameter par in SQLCommandObj.Parameters)
{
string key = par.ParameterName;
string value = par.Value as string;
query=query.Replace(key, value);
}
if (qParams.Count > 0)
{
SQLCommandObj.CommandText = "";
SQLCommandObj.CommandText = query;
}
SQLCommandObj.CommandTimeout = CustomCommandTimeout;
return SQLCommandObj.ExecuteReader(CommandBehavior.CloseConnection);
}

Using C# remove unnecessary “TABLE_NAME” from Excel worksheets

Can anyone tell me, I am going to upload excel file, this file has unnecessary table like "_xlnm#Print_Titles" that I need to remove or delete that field. This a my method. But it is does not work for remove or delete.
static string[] GetExcelSheetNames(string connectionString)
{
OleDbConnection con = null;
DataTable dt = null;
con = new OleDbConnection(connectionString);
con.Open();
dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if ((dt == null) )
{
return null;
}
String[] excelSheetNames = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheetNames[i] = row["TABLE_NAME"].ToString();
if ((excelSheetNames[i].Contains("_xlnm#Print_Titles") || (excelSheetNames[i].Contains("Print_Titles"))))
{
if (true)
{
row.Table.Rows.Remove(row);
dt.AcceptChanges();
}
}
i++;
}
return excelSheetNames;
}
Instead of removing items in the foreach loop, we'll find them and add them to a list, then we'll go through that list and remove them from your data table.
static string[] GetExcelSheetNames(string connectionString)
{
OleDbConnection con = null;
DataTable dt = null;
con = new OleDbConnection(connectionString);
con.Open();
dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if ((dt == null))
{
return null;
}
String[] excelSheetNames = new String[dt.Rows.Count];
var rowsToRemove = new List<DataRow>();
for (int i = 0; i < dt.Rows.Count; i++)
{
var row = dt.Rows[i];
excelSheetNames[i] = row["TABLE_NAME"].ToString();
if ((excelSheetNames[i].Contains("_xlnm#Print_Titles") || (excelSheetNames[i].Contains("Print_Titles"))))
{
rowsToRemove.Add(dt.Rows[i]);
}
i++;
}
foreach (var dataRow in rowsToRemove)
{
dt.Rows.Remove(dataRow);
}
return excelSheetNames;
}
Those _xlnm and "$" are sheets that, turns out, shouldn't be normally accessed by the users.
You can solve this in 2 ways.
Ignore them
Drop them
The former is highly recommended.
To do this you need to use the following code:
if (!dt.Rows[i]["Table_Name"].ToString().Contains("FilterDatabase") && !dt.Rows[i]["Table_Name"].ToString().EndsWith("$'"))
{
}
You can either use .Contains() and/or .EndsWith() to filter out those sheets.

Sending parameters to a stored procedure

Where is the problem in my code?
I use a stored procedure and transaction.
For one parameter to be working properly, but when the number of parameters is more than one error occurs.
Where is my problem?
This is my code in C#
internal static bool ExecuteNonQueryTransaction(string CommandName, CommandType cmdType, SqlParameter[][] pars)
{
int result = 0;
SqlTransaction tr = null;
int h = pars.GetLength(0);
using (SqlConnection con = new SqlConnection(CONNECTION_STRING))
{
if (con.State != ConnectionState.Open)
{
con.Open();
}
try
{
tr = con.BeginTransaction();
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandType = cmdType;
cmd.Transaction = tr;
cmd.CommandText = CommandName;
// cmd.Parameters.AddRange(pars);
for (int i = 0; i < pars.GetLength(0); i++)
{
cmd.Parameters.AddRange(pars[i]);
cmd.ExecuteNonQuery();
}
tr.Commit();
}
}
catch
{
if (tr != null)
{
tr.Rollback();
}
//return false;
}
}
return (result > 0);
}
and this my stored procedure
ALTER PROCEDURE dbo.AddNewUserTypePageAccess
(#id_user_type int,
#id_page_access int)
as
insert into user_type_page_access(id_user_type, id_page_access)
values(#id_user_type, #id_page_access)
return
Thank you for your help.....
You shouldn't call ExecuteNonQuery(); inside the loop that adds the parameters! Add all parameters, and then call ExecuteNonQuery(); once, with all the parameters in place.
Use this code:
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandType = cmdType;
cmd.Transaction = tr;
cmd.CommandText = CommandName;
// cmd.Parameters.AddRange(pars);
for (int i = 0; i < pars.GetLength(0); i++)
{
cmd.Parameters.AddRange(pars[i]);
}
// call ExecuteNonQuery only AFTER you've added all the parameters!
cmd.ExecuteNonQuery();
tr.Commit();
}

SQL command INSERT doesn't insert data into table, but debug shows it did (C#)

I can't get what is happening to my app. I'm using a SQL CE (.sdf file) to a local database (winform app) and when I debug, everything runs pretty well, I have in the end of it the message that my data was inserted well. But later on, when I check my databse, its empty.
What should I do?
This is my code:
SqlCeConnection conn = new SqlCeConnection(#"Data Source=|DataDirectory|\Database\Livraria.sdf;");
SqlCeCommand cmd = new SqlCeCommand();
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = #"INSERT INTO Livros (Codigo, ISBN, Titulo, Editora, Localizacao, Valor, QTD, Autor, AutorEspiritual, Data_)
VALUES (#Codigo, #ISBN, #Titulo, #Editora, #Localizacao, #Valor, #QTD, #Autor, #AutorEspiritual, #Data_)";
cmd.Parameters.AddWithValue("#Codigo", codigo);
cmd.Parameters.AddWithValue("#ISBN", isbn);
cmd.Parameters.AddWithValue("#Titulo", titulo);
cmd.Parameters.AddWithValue("#Editora", editora);
cmd.Parameters.AddWithValue("#Localizacao", localizacao);
cmd.Parameters.AddWithValue("#Valor", valor);
cmd.Parameters.AddWithValue("#QTD", entradas);
cmd.Parameters.AddWithValue("#Autor", autor);
cmd.Parameters.AddWithValue("#AutorEspiritual", autorEspiritual);
cmd.Parameters.AddWithValue("#Data_", data_);
try
{
conn.Open();
if (cmd.ExecuteNonQuery() > 0)
{
MessageBox.Show("Livro adicionado com sucesso!");
}
else
{
MessageBox.Show("O livro não foi adicionado.");
}
// Reset campos
Codigo.Text = "";
Titulo.Text = "";
Editora.SelectedIndex = 0;
Valor.SelectedIndex = 0;
Localizacao.SelectedIndex = 0;
Entrada.Text = "";
Isbn.Text = "";
Autor.SelectedIndex = 0;
AutorEspiritual.SelectedIndex = 0;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
conn.Close();
}
You have two databases. You are inserting to one and looking for the results in another.
Or, you are starting a transaction, inserting but then not committing.
The first thing you need to do is to create a simple select statement first that gets record from you sqlce database.
if( has record//connected )
{
//Proceed to your insert statement remove if else and use
conn.Open();
cmd.ExecuteNonQuery()
//then check your DB again
}
else
{
//Problem on you connection string
}
Your sqlce database is located on your bin folder
Regards