I am trying to display a column from my local database into a dropdown list. The problem is that I would need to split the data so that they are not displayed all in one line. I have used the ";" to separate the data and then using the split(";") method to split them. I have tried the code that I've wrote below but it's not working. Any help will be appreciated.
public string DisplayTopicNames()
{
string topicNames = "";
// declare the connection string
string database = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|/Forum.accdb;Persist Security Info=True";
// Initialise the connection
OleDbConnection myConn = new OleDbConnection(database);
//Query
string queryStr = "SELECT TopicName FROM Topics";
// Create a command object
OleDbCommand myCommand = new OleDbCommand(queryStr, myConn);
// Open the connection
myCommand.Connection.Open();
// Execute the command
OleDbDataReader myDataReader = myCommand.ExecuteReader();
// Extract the results
while (myDataReader.Read())
{
for (int i = 0; i < myDataReader.FieldCount; i++)
topicNames += myDataReader.GetValue(i) + " ";
topicNames += ";";
}
//Because the topicNames are seperated by a semicolon, I would have to split it using the split()
string[] splittedTopicNames = topicNames.Split(';');
// close the connection
myCommand.Connection.Close();
return Convert.ToString(splittedTopicNames);
}
You are returning just one column from the table.
There is no reason to use a for loop over a field count (it is always 1)
Instead you could use a List(Of String) to save the values returned by the rows found.
Then return this list to use as datasource for your DropDownList
List<string> topicNames = new List<string>();
// Extract the results
while (myDataReader.Read())
{
topicNames.Add(myDataReader.GetValue(0).ToString();
}
....
return topicNames;
However it is not clear if the field TopicName contains itself strings separated by semicolon.
In this case you could write:
List<string> topicNames = new List<string>();
// Extract the results
while (myDataReader.Read())
{
string[] topics = myDataReader.GetValue(0).ToString().Split(';')
topicNames.AddRange(topics);
}
...
return topicNames;
if you prefer to return an array of strings then it is just a matter to convert the list to an array
return topicNames.ToArray();
EDIT
Of course returning an array or a List(Of String) requires changes to the return value of your method
public List<string> DisplayTopicNames()
{
......
}
or
public string[] DisplayTopicNames()
{
......
}
if you still prefer to return a string separated by semicolons then change the return statement in this way
return string.Join(";", topicNames.ToArra());
Unless I've lost my mind, something like this should work:
while (myDataReader.Read())
{
for (int i = 0; i < myDataReader.FieldCount; i++)
ddl.Items.Add(myDataReader.GetValue(i))
}
where ddl is the name of your DropDownList. If your ddl isn't available here, then add them to a List<string> collection instead and return that. And then this code may now become irrelevant:
//Because the topicNames are seperated by a semicolon, I would have to split it using the split()
string[] splittedTopicNames = topicNames.Split(';');
// close the connection
myCommand.Connection.Close();
return Convert.ToString(splittedTopicNames);
but, on top of all this I want to restructure the code for you a little because you need to be leveraging things like using.
public string DisplayTopicNames()
{
string topicNames = "";
// declare the connection string
string database = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|/Forum.accdb;Persist Security Info=True";
// Initialise the connection
using (OleDbConnection myConn = new OleDbConnection(database))
{
myConn.Open();
// Create a command object
OleDbCommand myCommand = new OleDbCommand("SELECT TopicName FROM Topics", myConn);
// Execute the command
using (OleDbDataReader myDataReader = myCommand.ExecuteReader())
{
// Extract the results
while (myDataReader.Read())
{
for (int i = 0; i < myDataReader.FieldCount; i++)
{
ddl.Items.Add(myDataReader.GetValue(i));
}
}
}
}
// not sure anything needs returned here anymore
// but you'll have to evaluate that
return "";
}
The reason you want to leverage the using statement is to ensure that unmanaged resources that exist in the DataReader and Connection get disposed properly. When leaving the using statement it will automatically call Dispose on the object. This statement is only used for objects that implement IDisposable.
I think this should work:
public List<string> DisplayTopicNames()
{
List<string> topics = new List<string>();
// Initialise the connection
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|/Forum.accdb;Persist Security Info=True");
OleDbCommand cmd = new OleDbCommand("SELECT TopicName FROM Topics");
using(conn)
using(cmd)
{
cmd.Connection.Open();
// Execute the command
using(OleDbDataReader myDataReader = cmd.ExecuteReader())
{
// Extract the results
while(myDataReader.Read())
{
topics.Add(myDataReader.GetValue(0).ToString());
}
}
}
return topics;
}
Related
Trying to set up a connection to my local SQL Server Express instance so that I can display columns in a listbox. Th build runs fine and I can't see errors, but there is no data in the listbox. I have tested the query and that is fine. I am using NT Authentication to the database. Any ideas where I might have gone wrong?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void customers_SelectedIndexChanged(object sender, EventArgs e)
{
string commstring = "Driver ={SQL Server}; Server = DESKTOP-5T4MHHR\\SQLEXPRESS; Database = AdventureWorks2014; Trusted_Connection = Yes;";
string connstring = "SELECT FirstName, LastName FROM Person.Person";
SqlDataAdapter customerDataAdapater = new SqlDataAdapter(commstring, connstring);
DataSet customerDataSet = new DataSet();
customerDataAdapater.Fill(customerDataSet, "Person.Person");
DataTable customerDataTable = new DataTable();
customerDataTable = customerDataSet.Tables[0];
foreach (DataRow dataRow in customerDataTable.Rows)
{
customers.Items.Add(dataRow["FirstName"] + " (" + dataRow["LastName"] + ")");
}
}
}
I tested your code in a sample project here and I realized you passed the parameters to SqlDataAdapter constructor in a wrong order.
After changing the follow line:
SqlDataAdapter customerDataAdapater = new SqlDataAdapter(commstring, connstring);
by
SqlDataAdapter customerDataAdapater = new SqlDataAdapter(connstring, commstring);
the listbox was filled successfully.
Your connection string seems weird.....
Could you try using just this:
string commstring = "Server=DESKTOP-5T4MHHR\\SQLEXPRESS;Database=AdventureWorks2014;Trusted_Connection=Yes;";
Also: why are you first creating a DataSet, filling in a single set of data, and then extracting a DataTable from it?? This is unnecessarily complicated code - just use this instead:
SqlDataAdapter customerDataAdapater = new SqlDataAdapter(commstring, connstring);
// if you only ever need *one* set of data - just use a DataTable directly!
DataTable customerDataTable = new DataTable();
// Fill DataTable with the data from the query
customerDataAdapater.Fill(customerDataTable);
Update: I would really rewrite your code to something like this:
// create a separate class - call it whatever you like
public class DataProvider
{
// define a method to provide that data to you
public List<string> GetPeople()
{
// define connection string (I'd really load that from CONFIG, in real world)
string connstring = "Server=MSEDTOP;Database=AdventureWorks2014;Trusted_Connection=Yes;";
// define your query
string query = "SELECT FirstName, LastName FROM Person.Person";
// prepare a variable to hold the results
List<string> entries = new List<string>();
// put your SqlConnection and SqlCommand into "using" blocks
using (SqlConnection conn = new SqlConnection(connstring))
using (SqlCommand cmd = new SqlCommand(query, conn))
{
conn.Open();
// iterate over the results using a SqlDataReader
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// get first and last name from current row of query
string firstName = rdr.GetFieldValue<string>(0);
string lastName = rdr.GetFieldValue<string>(1);
// add entry to result list
entries.Add(firstName + " " + lastName);
}
rdr.Close();
}
conn.Close();
}
// return the results
return entries;
}
}
And in your code-behind, you only need to do something like this:
protected override void OnLoad(.....)
{
if (!IsPostback)
{
List<string> people = new DataProvider().GetPeople();
customers.DataSource = people;
customers.DataBind();
}
}
but I still don't understand what you were trying to when the SelectedIndexChanged event happens.....
I am trying to populate a group of labels in a C# windows form with some values that are in a certain attribute (PlayerName) in a database that I have in access.
Currently the only code I have is:
OleDbConnection connection = new OleDbConnection(CONNECTION STRING HERE);
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = "SELECT PlayerName FROM [TotalPlayerName] WHERE Team = 1 AND SportID = " + Form1.IDNumber;
I need a list or array that holds these values so I can use them to populate the labels, but I am unaware of how to do this.
You need to call ExecuteReader to obtain a data reader and then loop through the rows of the result set like this:
List<string> result = new List<string>();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
result.Add(reader.GetString(0));
}
}
Before you do this, don't forget to open the connection like this:
connection.Open();
There are a couple of things here..... for sake of best practice well its more standard practice... as I like to say!
Use USING as this cleans up after connection.. see here for great examples in a "using" block is a SqlConnection closed on return or exception?
using (OdbcDataReader DbReader = DbCommand.ExecuteReader())
{
int fCount = DbReader.FieldCount;
while (DbReader.Read())
{
Label1 = DbReader.GetString(0);
Label2 = DbReader.GetString(1);
Label3 = DbReader.GetString(2);
Label4 = DbReader.GetString(3);
for (int i = 0; i < fCount; i++)
{
String col = DbReader.GetString(i);
Console.Write(col + ":");
}
Console.WriteLine();
}
}
NB your SQL only return 1 field /String at the moment
while reading the data fill the list like
List<string> players = new List<string>();
OleDbDataReader rdr = command.ExecuteReader();
While(rdr.Read())
{
players.Add(rdr["PlayerName"].ToString());
}
You need to create a OleDbReader object to read the response from the query. You will also need to create a List to store the data Something like this:
List<string> playerNameList = new List<string>();
using (OleDbReader r = command.ExecuteReader())
{
while(reader.Read())
{
playerNameList.Add(reader.GetString(0));
}
}
One option might be using OleDbDataAdapter to fill a DataTable those values that returns your query;
var dt = new DataTable();
using(var da = new OleDbDataAdapter(command))
{
da.Fill(dt);
}
And since your query return one column, you can use AsEnumerable to that datatable to get them as a string like;
List<string> list = dt.AsEnumerable()
.Select(r => r.Field<string>("PlayerName"))
.ToList();
You can read: Queries in LINQ to DataSet
By the way, you should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Also use using statement to dispose your connection and command automatically as I did for OleDbDataAdapter in my example.
I have a built a system which loads words from a database table but I need to add those words to a list of type "Choices" (the type that is needed for Grammar Building).
This is my code for requesting words to be retrieved from the database:
List<string> newWords = new List<string>();
newWords = LexicalOperations.WordLibrary().ToList();
Choices dbList = new Choices(); //Adding them to a Choice List
if (newWords.Count != 0)
{
foreach (string word in newWords)
{
dbList.Add(word.ToString());
}
}
else dbList.Add("Default");
This is my code of retrieving data from the table:
public class LexicalOperations
{
public static List<string> WordLibrary()
{
List<string> WordLibrary = new List<string>();
string conString = "Data Source=.;Initial Catalog=QABase;Integrated Security=True";
using (SqlConnection connection = new SqlConnection(conString))
{
connection.Open();
string sqlIns = "select WordList from NewWords";
SqlCommand cmd = new SqlCommand(sqlIns, connection);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
sda.Fill(ds);
foreach (DataRow dr in ds.Tables[0].Rows)
{
WordLibrary.Add(dr[0].ToString());
}
}
return WordLibrary;
}
}
HOWEVER, This throws an exception: System.FormatException which also states the message:
FormatException was unhandled
Double-quoted string not valid.
This error is thrown when I build the choices list in a Speech Grammar Builder:
GrammarBuilder graBui = new GrammarBuilder(dbList);
Grammar Gra = new Grammar(graBui);
What am I doing wrong? What should be done in order to properly retrieve words from the database and add them to a Choice list?
The problem seems to be that your Grammar class cannot handle strings with double quotes.
So, the simplest way to remove the problem is to remove the double quotes by your input.
public class LexicalOperations
{
public static List<string> WordLibrary()
{
List<string> WordLibrary = new List<string>();
string conString = "Data Source=.;Initial Catalog=QABase;Integrated Security=True";
string sqlIns = "select WordList from NewWords";
using (SqlConnection connection = new SqlConnection(conString))
using (SqlCommand cmd = new SqlCommand(sqlIns, connection))
{
connection.Open();
using(SqlDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
string noQuotes = reader.GetString(0).Replace("\"", "");
WordLibrary.Add(noQuotes);
// In alternative you could also opt to not add a string with double quotes
// string noQuotes = reader.GetString(0);
// if(noQuotes.IndexOf("\"") < 0)
// WordLibrary.Add(noQuotes);
}
}
}
return WordLibrary;
}
}
Notice that I have also removed the SqlDataAdapter and the filling of a DataSet. In this context is useless and clearly hinders the performance because you are executing two loops. The first one is executed by the Framework to fill the DataSet, the second by your code to add the words to the List<string> variable
I have added some data from the local database to a List, and now I need to show the values this List has inside a dropdownlist. The List contains the following data:
Java
.net
JavaScript
Ruby
Python
Method:
public List<string> DisplayTopicNames()
{
// declare the connection string
string database = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|/Forum.accdb;Persist Security Info=True";
// Initialise the connection
OleDbConnection myConn = new OleDbConnection(database);
//Query
string queryStr = "SELECT TopicName FROM Topics";
// Create a command object
OleDbCommand myCommand = new OleDbCommand(queryStr, myConn);
// Open the connection
myCommand.Connection.Open();
// Execute the command
OleDbDataReader myDataReader = myCommand.ExecuteReader();
// Extract the results
List<string> topicNames = new List<string>();
while (myDataReader.Read())
{
topicNames.Add(myDataReader.GetValue(0).ToString());
}
// close the connection
myCommand.Connection.Close();
return topicNames;
}
}
When I return the above method on its own it works fine and all the values are there but When I use the following code to add this List to the dropdownlist it only shows "j" "a" "v" "a" which is very strange.
DropDownList1.DataSource = dt.DisplayTopicNames();
DropDownList1.DataBind();
Instead of:
topicNames.Add(myDataReader.GetValue(0).ToString());
try this:
topicNames.Add(myDataReader["TopicName"].ToString());
I'm struggling. I have query against my db that returns a single column of data and I need to set it as List. Here is what I am working with and I am getting an error about converting void to string.
public static void GetImportedFileList()
{
using (SQLiteConnection connect = new SQLiteConnection(#"Data Source=C:\Documents and Settings\js91162\Desktop\CMMData.db3"))
{
connect.Open();
using (SQLiteCommand fmd = connect.CreateCommand())
{
SQLiteCommand sqlComm = new SQLiteCommand(#"SELECT DISTINCT FileName FROM Import");
SQLiteDataReader r = sqlComm.ExecuteReader();
while (r.Read())
{
string FileNames = (string)r["FileName"];
List<string> ImportedFiles = new List<string>();
}
connect.Close();
}
}
}
Then later in application
List<string> ImportedFiles = GetImportedFileList() // Method that gets the list of files from the db
foreach (string file in files.Where(fl => !ImportedFiles.Contains(fl)))
public static List<string> GetImportedFileList(){
List<string> ImportedFiles = new List<string>();
using (SQLiteConnection connect = new SQLiteConnection(#"Data Source=C:\Documents and Settings\js91162\Desktop\CMMData.db3")){
connect.Open();
using (SQLiteCommand fmd = connect.CreateCommand()){
fmd.CommandText = #"SELECT DISTINCT FileName FROM Import";
fmd.CommandType = CommandType.Text;
SQLiteDataReader r = fmd.ExecuteReader();
while (r.Read()){
ImportedFiles.Add(Convert.ToString(r["FileName"]));
}
}
}
return ImportedFiles;
}
Things i've amended in your code:
Put ImportedFiles in scope of the entire method.
No need to call connect.Close(); since the connection object is wrapped in a using block.
Use Convert.ToString rather then (String) as the former will handle all datatype conversions to string. I came across this Here
Edit:
You were creating a new command object sqlComm instead of using fmd that was created by the connection object.
First of all your return type is void. You need to return a List. Another problem is that you initialize the list inside the loop, so in each pass of the loop you have a new list, and whatsmore, you do not add the string in the list. Your code should probably be more like:
public static List<string> GetImportedFileList()
{
List<string> ImportedFiles = new List<string>();
using (SQLiteConnection connect = new SQLiteConnection(#"Data Source=C:\Documents and Settings\js91162\Desktop\CMMData.db3"))
{
connect.Open();
using (SQLiteCommand fmd = connect.CreateCommand())
{
fmd.CommandText = #"SELECT DISTINCT FileName FROM Import";
SQLiteDataReader r = fmd.ExecuteReader();
while (r.Read())
{
string FileNames = (string)r["FileName"];
ImportedFiles.Add(FileNames);
}
connect.Close();
}
}
return ImportedFiles;
}
The error is about the return type of your method. You are returning void (public staticvoid) but then use it later as if it were returning a List<string>.
I think you intended the following method signature:
public static List<string> GetImportedFileList()
You already have a way to get the individual results, so to me it looks like you just need to:
Move the List<string> ImportedFiles = new List<string>(); outside the while loop.
Call ImportedFiles.Add(FileNames); inside the loop (after that string gets assigned).
return ImportedFiles at the end.
Change the return type to List<string>.