I am trying to read values form my database. But why am I getting only values with no column name?
this is my controller. that returns the values in JSON
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "SELECT DISTINCT State FROM MyDBtable";
con.Open();
List<string> StateList = new List<string>();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
StateList.Add(reader[0].ToString());
}
return Json(new
{
myTable = StateList
}, JsonRequestBehavior.AllowGet);
and this is my JSON
{"myTable":["VA","CA"]}
Where as, it's suppose to give me
{"myTable":[{"State":"VA"},{"State":"CA"}]}
Why is it not reading and printing State
String does not have property "State". Create anonymous type instead:
myTable = StateList.Select(s => new { State = s })
UPDATE: Easiest solution for multiple columns - create a DTO for that
public class MyItem // of course use more descriptive name
{
public string State { get; set; }
public string Capital { get; set; }
// etc
}
And fill it from reader:
List<MyItem> items = new List<MyItem>();
while (reader.Read())
{
MyItem item = new MyItem();
item.State = reader[0].ToString();
item.Capital = reader[1].ToString();
// etc
items.Add(item);
}
return Json(new { myTable = items }, JsonRequestBehavior.AllowGet);
One more sample (with Dapper, which you can find on NuGet). Add using Dapper; to your code. Use same DTO class, as above.
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
return Json(new {
myTable = connection.Query<MyItem>("SELECT * FROM MyDBtable").ToList()
}, JsonRequestBehavior.AllowGet);
}
Because you are selecting state. This will create a new object where the State property is assigned the state, such that you get what you want:
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "SELECT DISTINCT State FROM MyDBtable";
con.Open();
List<string> StateList = new List<string>();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
StateList.Add(reader[0].ToString());
}
return Json(new
{
myTable = StateList.Select(i => new { State = i })
}, JsonRequestBehavior.AllowGet);
For additional columns, see lazyberezovsky's answer who has changed StateList to solve this.
Related
This method retrieves the entire data.
I'm trying to switch this method to a method that uses a dictionary but it doesn't work very well.
INSERT, UPDATE, and DELETE completed but I'm having trouble with SELECT.
I want convert to the my method like below link source.
https://gist.github.com/thorsman99/e788dd9cce36c26edd9076c9dac288dd
public static List<TestModel> GetList(string id, string subject, string UseYN, string createDate1, string createDate2)
{
using(SQLiteConnection connection = new SQLiteConnection(_connection))
{
connection.Open();
using(SQLiteCommand command = new SQLiteCommand(connection))
{
command.CommandText = #"SELECT ID, Subject, CreateDate, UpdateDate FROM Test";
command.Parameters.Add(new SQLiteParameter(#"ID" , DbType.String) { Value = id });
command.Parameters.Add(new SQLiteParameter(#"Subject" , DbType.String) { Value = subject });
command.Parameters.Add(new SQLiteParameter(#"CreateDate1", DbType.String) { Value = createDate1 });
command.Parameters.Add(new SQLiteParameter(#"CreateDate2", DbType.String) { Value = createDate2 });
SQLiteDataReader reader = command.ExecuteReader();
List<TestModel> list = new List<TestModel>();
while(reader.Read())
{
TestModel item = new TestModel();
item.ID = reader["ID" ].ToString();
item.Subject = reader["Subject" ].ToString();
item.CreateDate = Convert.ToDateTime(reader["CreateDate"]);
item.UpdateDate = Convert.ToDateTime(reader["UpdateDate"]);
list.Add(item);
}
return list;
}
}
}
I moved connection.Open to directly before the.ExecuteReader` Connections should be open for the shortest possible time. I moved the declare of the Dictionary outside the using block and then the return outside also. This again is to close the connection as soon as possible.
I combined the 2 using blocks to one. Just simplifies the code a bit and saves indenting.
For the dictionary, I used "ID" as the key. I assumed that this was the Primary Key and therefore unique.
public Dictionary<string, TestModel> GetTestModelDictionary(string id, string subject, string UseYN, string createDate1, string createDate2)
{
Dictionary<string, TestModel> dict = new Dictionary<string, TestModel>();
using (SQLiteConnection connection = new SQLiteConnection(_connection))
using (SQLiteCommand command = new SQLiteCommand(connection))
{
command.CommandText = #"SELECT ID, Subject, CreateDate, UpdateDate FROM Test";
command.Parameters.Add(new SQLiteParameter(#"ID", DbType.String) { Value = id });
command.Parameters.Add(new SQLiteParameter(#"Subject", DbType.String) { Value = subject });
command.Parameters.Add(new SQLiteParameter(#"CreateDate1", DbType.String) { Value = createDate1 });
command.Parameters.Add(new SQLiteParameter(#"CreateDate2", DbType.String) { Value = createDate2 });
connection.Open();
SQLiteDataReader reader = command.ExecuteReader();
while (reader.Read())
{
TestModel item = new TestModel();
item.ID = reader["ID"].ToString();
item.Subject = reader["Subject"].ToString();
item.CreateDate = Convert.ToDateTime(reader["CreateDate"]);
item.UpdateDate = Convert.ToDateTime(reader["UpdateDate"]);
dict.Add(item.ID, item);
}
}
return dict;
}
I have a method in my controller class that is supposed to return the results from a raw SQL query inside the method. The problem is I can't pull return more than one column result to the list in a query that is supposed to return multiple column results.
I know that the problem has to do with how I am adding to the results list during the Read, but I am unsure how to structure this properly to return multiple values.
Here is my current method:
public IActionResult Search ([FromRoute]string input)
{
string sqlcon = _iconfiguration.GetSection("ConnectionStrings").GetSection("StringName").Value;
List<string> results = new List<string>();
using (var con = new SqlConnection(sqlcon))
{
using (var cmd = new SqlCommand()
{
CommandText = "SELECT u.UserID, u.User FROM [dbo].[Users] u WHERE User = 'Value';",
CommandType = CommandType.Text,
Connection = con
})
{
con.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
results.Add(reader.GetString(0));
}
con.Close();
return Ok(new Search(results));
}
}
}
}
The SQL query is supposed to return the UserID and User based on the entered User, however, only the User gets returned here.
Does anyone know what I am missing to return multiple column names for this SQL query and method? Any advice would be greatly appreciated.
FYI, I can't use a stored procedure here, I do not have permission to create an SP on this database.
You can create a class for the results of the Query
public class ClassForResults(){
public int UserID { get; set; };
public string User { get; set; }
}
public IActionResult Search ([FromRoute]string input)
{
string sqlcon = _iconfiguration.GetSection("ConnectionStrings").GetSection("StringName").Value;
List<ClassForResults> results = new List<ClassForResults>();
using (var con = new SqlConnection(sqlcon))
{
using (var cmd = new SqlCommand()
{
CommandText = "SELECT u.UserID, u.User FROM [dbo].[Users] u WHERE User = 'Value';",
CommandType = CommandType.Text,
Connection = con
})
{
con.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
ClassForResults result = new ClassForResults();
result.UserID = reader.GetInt(0);
result.User = reader.GetString(1);
results.Add(result);
}
con.Close();
return Ok(new Search(results));
}
}
}
}
Why only the else condition runs? Postalcode column is float, City column is nvarchar. I think the fail is the string may be mistake.
private void txt_st_postalcode_Leave(object sender, EventArgs e)
{
using (var connection = new SqlConnection("Data Source=mypublicip\\SQLEXPRESS2017;Initial Catalog=studentreg; User = myusername; Password=mypassword;"))
{
connection.Open();
using (var command = new SqlCommand("SELECT City FROM Cities WHERE Postcode=#Postcode", connection))
{
command.Parameters.AddWithValue("#Postcode", "10101");
using (var reader = command.ExecuteReader())
{
string txt_st_postalcode = reader.Read() ?
reader[1] as string : ("City");
if (reader.Read())
{
txt_st_city.Text = reader.GetString(reader.GetOrdinal("City"));
}
else
{
MessageBox.Show("Sh*t!");
}
}
}
}
}
Not too sure how these postcodes work (different in the UK), but given that you're using ExecuteReader you appear to be expecting multiple results. As the comments have pointed out, you're currently reading the results twice; however, you should probably have some form of loop; for example:
using (var command = new SqlCommand("SELECT City FROM Cities WHERE Postcode=#Postcode", connection))
{
command.Parameters.AddWithValue("#Postcode", "10101");
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
string txt_st_postalcode = reader[0] as string;
//txt_st_city.Text = reader.GetString(reader.GetOrdinal("City"));
// Depends what you're doing here?
}
}
}
If you only expect a single result, try using ExecuteScalar() which will return a single result; for example:
using (var command = new SqlCommand("SELECT City FROM Cities WHERE Postcode=#Postcode", connection))
{
command.Parameters.AddWithValue("#Postcode", "10101");
txt_st_city.Text = command.ExecuteScalar();
}
Firstly, if you need to read PostCode from the reader, you have to select first. So, change your query.
using (var command = new SqlCommand("SELECT City, PostCode FROM Cities WHERE Postcode=#Postcode", connection))
Secondly, calling read once per row before getting data.
if (reader.Read())
{
txt_st_postalcode .Text = reader.GetString(reader.GetOrdinal("PostCode"));
txt_st_city.Text = reader.GetString(reader.GetOrdinal("City"));
}
else
{
MessageBox.Show("Sh*t!");
}
I'm creating a list <object> and here I'm adding my data from a database.
But I totally don't know how to deal with a list <object>.
public class ClassList
{
public int Name { get; set; }
public string Birthday { get; set; }
}
private void GetClassList()
{
SqlConnection conn = new SqlConnection(GlobalVar.ConnString);
SqlCommand cmd = new SqlCommand
("SELECT * " +
"FROM Class_Data ", conn);
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
try
{
List<ClassList> ClassList = new List<ClassList>();
while (dr.Read())
{
ClassList.Add(new ClassList()
{
Name = ___?___, //what should i write here
Birthday = ___?___ //and here
});
}
}
catch{}
finally
{
dr.Close();
conn.Close();
}
}
Having been looking for lots of information but still fail to work it out.
I will be very appreciated if someone could help!
This should do it:
List<ClassList> ClassList = new List<ClassList>();
while (dr.Read())
{
ClassList.Add(new ClassList()
{
Name = (int)dr["Name"], //the name of the db column
Birthday = dr["Birthday"].ToString();
});
}
As a side note, it maybe worth altering your query from SELECT *... to just selecting the columns you require, from readability/maintenance point of view.
Also, is Name really an int seems like it could be a string.
You can also refer to the documentation:
SqlDataReader.Item Property (String)
You can use column name that are return by your database query with dr like dr["ColumnName"]
ClassList.Add(new ClassList()
{
Name = dr["NameColum"], //what should i write here
Birthday = dr["BrithColum"] //and here
});
Something like that:
// You don't use "this" in the context
// It seems, that you want to return the collected data (List<ClassList>)
private static List<ClassList> GetClassList() {
// Put IDisposable into using
using (SqlConnection conn = new SqlConnection(GlobalVar.ConnString)) {
conn.Connect();
// You want to fetch two fields only, right? Not the entire table (*)
String sql =
#"select Name,
BirthDay
from Class_Data"
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
List<ClassList> result = new List<ClassList>();
using (SqlDataReader dr = cmd.ExecuteReader()) {
while (dr.Read()) {
result.Add(new ClassList() {
Name = Convert.ToString(dr[0]),
Birthday = Convert.ToDateTime(dr[1])
});
}
}
return result;
}
}
}
You can access the column values with dr["ColumnName"].
I am getting data from SQL and putting it in list. here's what I am trying now,
public class Fruit //custom list
{
public string aID { get;set; } // can be more then 1
public string bID { get;set; } // only 2 but different aID
public string name { get;set; } // only 1 for selection of aID and bID
}
and this is how i am getting data from sql,
var Fruitee = new Fruit();
using (SqlConnection cn = new SqlConnection(CS()))
{
cn.Open();
SqlCommand sqlCommand= new SqlCommand("SELECT * FROM myTable", cn);
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read())
{
Fruitee.add(reader["aID"], reader["bID"],reader["name"]) // ??? not sure what to put here as add is not available
}
cn.Close();
}
Table looks like this,
aID, bID, name
**
Problem
**
I am stuck how to add items to list and also is it best practice ?
List<Fruit> fruits = new List<Fruit>();
while (reader.Read())
{
Fruit f = new Fruit();
f.aID = (string) reader["aID"];
f.bID = (string) reader["bID"];
f.name = (string) reader["name"];
fruits.Add(f);
}
var list = new List<Fruit>();
while (reader.Read())
{
list.Add(new Fruit() { aID = reader["aID"].ToString(), bID = reader["bID"].ToString(), name = reader["name"].ToString() });
}
var Fruitee = new List<Fruit>();
while (reader.Read())
{
Fruitee.Add(new Fruit() { aID = reader["aID"].ToString(), bID = reader["bID"].ToString(), name = reader["name"].ToString() });
}
You need to actually read from the reader and that's what you're not doing. However, be aware of DBNulls.
So assuming that your custom list has an add function you could do something like the following.
while(reader.Read())
{
Fruitee.add(reader["aID"], reader["bID"], reader["name"]);
}