Consider a Winforms app connecting to a SQL Server 2008 database and running a SQL SELECT statement:
string myConnectionString = "Provider=SQLOLEDB;Data Source=hermes;Initial Catalog=qcvaluestest;Integrated Security=SSPI;";
string mySelectQuery = "SELECT top 500 name, finalconc from qvalues where rowid between 0 and 25000;";
OleDbConnection myConnection = new OleDbConnection(myConnectionString);
OleDbCommand myCommand = new OleDbCommand(mySelectQuery, myConnection);
myCommand.Connection.Open();
OleDbDataReader myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
How can you read the results of the query into a list?
Assume you have defined a class that is something like
class MyData
{
public string Name {get; set;}
public int FinalConc {get; set;} // or whatever the type should be
}
You would iterate through the results of your query to load a list.
List<MyData> list = new List<MyData>();
while (myReader.Read())
{
MyData data = new MyData();
data.Name = (string)myReader["name"];
data.FinalConc = (int)myReader["finalconc"]; // or whatever the type should be
list.Add(data);
}
// work with the list
If you just need one of the given fields, you can forego the class definition and simply have a List<T>, where T is the type of whatever field you want to hold.
You can try something as (adapt it for your convenience):
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
List<Person> dbItems = new List<Person>();
while(myReader.Read())
{
Person objPerson = new Person();
objPerson.Name = Convert.ToString(myReader["Name"]);
objPerson.Age = Convert.ToInt32(myReader["Age"]);
dbItems.Add(objPerson);
}
List of what? Do you have a class setup that has properties for name and finalconc? Saying you do, and it looks like this:
public class QueryResult
{
public string Name { get; set; }
//not sure what finalconc type would be, so here just using string
public string FinalConc { get; set; }
}
Then you would do something like this:
var queryResults = new List<QueryResult>();
using(var myReader = myCommand.ExecuteReader())
{
while(myReader.Read())
{
queryResults.Add(new QueryResult
{
Name = myReader.GetString(myReader.GetOrdinal("name")),
FinalConc = myReader.GetString(myReader.GetOrdinal("finalconc"))
});
}
}
Related
I'm kind a new on c#. I have a problem with to store the className to list since i need to display all the class that teacher taught. On result, it turns out just the last class teacher taught. I did use join table between teacher and classes.
Model
public class Teacher
{
public int teacherId { get; set; }
public string teacherfName { get; set; }
public string teacherlName { get; set; }
public string className { get; set; }
public int classId { get; set; }
}
Controller
public Teacher FindTeacher(int id)
{
Teacher newTeacher = new Teacher();
MySqlConnection Conn = school.AccessDatabase();
Conn.Open();
MySqlCommand cmd = Conn.CreateCommand();
//SQL QUERY
cmd.CommandText = "Select * from teachers left join classes on teachers.teacherid=classes.teacherid where teachers.teacherid = " + id;
//Gather Result Set of Query into a variable
MySqlDataReader ResultSet = cmd.ExecuteReader();
while (ResultSet.Read())
{
int teacherId = (int)ResultSet["teacherId"];
string teacherfName=ResultSet["teacherfname"].ToString();
string teacherlName=ResultSet["teacherlname"].ToString();
newTeacher.teacherId = teacherId;
newTeacher.teacherFName = teacherFName;
newTeacher.teacherLName = teacherLName;
newTeacher.className = className;
newTeacher.classId = (int)ResultSet["classid"];
}
return newTeacher;
}
Your only returning one teacher if you want all the teachers your code should be:
public IEnumerable<Teacher> FindTeacher(int id)
{
//Lise here
List<Teacher> teachers = new List<Teacher>();
//note the using
using MySqlConnection Conn = school.AccessDatabase();
Conn.Open();
//note the using
using MySqlCommand cmd = Conn.CreateCommand();
//SQL QUERY
cmd.CommandText = "Select * from teachers left join classes on teachers.teacherid=classes.teacherid where teachers.teacherid = " + id;
//Gather Result Set of Query into a variable
MySqlDataReader ResultSet = cmd.ExecuteReader();
while (ResultSet.Read())
{
//new teacher in the loop
Teacher newTeacher = new Teacher();
int teacherId = (int)ResultSet["teacherId"];
string teacherfName=ResultSet["teacherfname"].ToString();
string teacherlName=ResultSet["teacherlname"].ToString();
newTeacher.teacherId = teacherId;
newTeacher.teacherFName = teacherFName;
newTeacher.teacherLName = teacherLName;
newTeacher.className = className;
newTeacher.classId = (int)ResultSet["classid"];
//add to the collection
teachers.Add(newTeacher);
}
//return the collection
return teachers;
}
If also added using statements. These are important to prevent memory leaks
Modify Teacher Class to be able to carry List of TeacherClass that correspond to one teacher:
Define New Class TeacherClass to Carry a TeacherClass Data
public class TeacherClass
{
public string Name { get; set; }
public int Id { get; set; }
}
Modify Teacher Class To have a List Of TeacherClass
public class Teacher
{
public int teacherId { get; set; }
public string teacherfName { get; set; }
public string teacherlName { get; set; }
public List<TeacherClass> classes { get; set; } = new List<TeacherClass>();
}
Then get your function to set this TeacherClass List in a loop:
public Teacher FindTeacher(int id)
{
Teacher newTeacher = new Teacher();
//note the using
using MySqlConnection Conn = school.AccessDatabase();
Conn.Open();
//note the using
using MySqlCommand cmd = Conn.CreateCommand();
//SQL QUERY
cmd.CommandText = "Select * from teachers left join classes on teachers.teacherid=classes.teacherid where teachers.teacherid = " + id;
//Gather Result Set of Query into a variable
MySqlDataReader ResultSet = cmd.ExecuteReader();
// Check if any rows retrieved
if (reader.HasRows)
{
// Iterate Over Rows
while (ResultSet.Read())
{
// Set Teacher Data Just Once
if(newTeacher.teacherId == 0){
newTeacher.teacherId = (int)ResultSet["teacherId"];;
newTeacher.teacherFName = ResultSet["teacherfname"].ToString();
newTeacher.teacherLName = ResultSet["teacherlname"].ToString();
}
// Add new TeacherClass data for this teacher
newTeacher.classes.Add(
new TeacherClass(){
Name = className, // className Check this variable as it is not declared
Id = (int)ResultSet["classid"]
});
}
}
return newTeacher;
}
I am making a web service get data from sql server. I need to get many fields from the sql server, but I can only get one field, which is the Currancy Name
namespace WebApplication2
{
public class DataHelper
{
public static string GetCurrency(string currencyCode)
{
string currencyName = "";
SqlConnection con = new SqlConnection(#"Data Source=WEB3\SHAREPOINT;Initial Catalog=WSS_Search_WEB3;Integrated Security=True");
SqlCommand cmd = new SqlCommand("select PO_NUMBER,PO_STATUS from View_1 where PO_HEADER_ID ='" + currencyCode.ToUpper() + "'", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
currencyName = dr["PO_NUMBER"].ToString();
}
dr.Close();
con.Close();
return currencyName;
}
}
}
I need to get the PO_Number & PO Status from the Query
As I understand you need to return not only PO_NUMBER, but also PO_STATUS, and as I understand you want to return both values.
I suggest you make model that represent what you want to return.
So for that we make a model class call it for instance POModel:
public class POModel
{
public string currencyName { get; set; } // PO_Number
public string statusName { get; set; } // PO_Status
}
Than fetch the values from SQL as you did and return object in stead of string.
Here would you final code looks like, of course naming and all the stuff you can change the way if fits best:
public class DataHelper
{
public static POModel GetCurrency(string currencyCode)
{
//string currencyName = "";
var poModel = new POModel();
SqlConnection con = new SqlConnection(#"Data Source=WEB3\SHAREPOINT;Initial Catalog=WSS_Search_WEB3;Integrated Security=True");
SqlCommand cmd = new SqlCommand("select PO_NUMBER,PO_STATUS from View_1 where PO_HEADER_ID ='" + currencyCode.ToUpper() + "'", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
poModel.currencyName = dr["PO_NUMBER"].ToString();
poModel.statusName = dr["PO_STATUS"].ToString();
}
dr.Close();
con.Close();
//return currencyName;
return poModel;
}
}
public class POModel
{
public string currencyName { get; set; }
public string statusName { get; set; }
}
One option is to return an array that contains the two values. Notice string[]:
public static string[] GetCurrency(string currencyCode)
Similar to how you declared string currencyName = "";, instead make an array variable:
string[] poData = new string[2];
Since this looks like it should return a single row, I would not loop. Just do a Read():
dr.Read();
poData[0] = dr["PO_NUMBER"].ToString(); //poData[] will have to be declared in your method
poData[1] = dr["PO_STATUS"].ToString();
....
return poData;
I'm trying to add data into a database using a foreach loop to iterate through lists which contain values of different types.
List<string> productCodeList = new List<string>();
List<string> productNameList = new List<string>();
List<string> productPriceList = new List<string>();
List<int> competitorList = new List<int>();
List<DateTime> dateCreatedList = new List<DateTime>();
Is there a way to iterate through multiple lists with different types? Because at the moment I'm only able to insert one list to one column. What I want is to insert data to all the columns specified.
Or is there possibly a better way of doing this?
using (var con = new SqlConnection(connectionString))
{
con.Open();
using (var cmd = new SqlCommand(#"INSERT INTO OnlineProductsTemp$(CompetitorID, ProductCode, ProductName, Price, DateCreated)
VALUES(#CompetitorID, #ProductCode, #ProductName, #Price, #DateCreated)", con))
{
cmd.Parameters.Add("#CompetitorID", SqlDbType.Int);
cmd.Parameters.Add("#ProductCode", SqlDbType.VarChar);
cmd.Parameters.Add("#ProductName", SqlDbType.VarChar);
cmd.Parameters.Add("#Price", SqlDbType.Decimal);
cmd.Parameters.Add("#DateCreated", SqlDbType.DateTime);
foreach (var value in competitorList)
{
cmd.Parameters["#CompetitorID"].Value = value;
int rowsAffected = cmd.ExecuteNonQuery();
}
competitorList.Clear();
}
}
Thanks in advance!
You have logically related properties like name, code etc split into multiple lists which would be hard to maintain and error prone like #Santiago pointed out.
If you have complete control over the code, you may consider creating a Product class and having a collection of Products.
public class Product
{
public string Code { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int CompetitorId { get; set; }
public DateTime DateCreated { get; set; }
}
public class DemoClass
{
public static void Demo()
{
var products = new List<Product>();
// fill the list here
using (var con = new SqlConnection(connectionString))
{
con.Open();
using (var cmd = new SqlCommand(#"INSERT INTO OnlineProductsTemp$(CompetitorID, ProductCode, ProductName, Price, DateCreated)
VALUES(#CompetitorID, #ProductCode, #ProductName, #Price, #DateCreated)", con))
{
cmd.Parameters.Add("#CompetitorID", SqlDbType.Int);
cmd.Parameters.Add("#ProductCode", SqlDbType.VarChar);
cmd.Parameters.Add("#ProductName", SqlDbType.VarChar);
cmd.Parameters.Add("#Price", SqlDbType.Decimal);
cmd.Parameters.Add("#DateCreated", SqlDbType.DateTime);
foreach (var p in products)
{
cmd.Parameters["#CompetitorID"].Value = p.CompetitorId;
cmd.Parameters["#ProductCode"].Value = p.Code;
cmd.Parameters["#ProductName"].Value = p.Name;
cmd.Parameters["#Price"].Value = p.Price;
cmd.Parameters["#DateCreated"].Value = p.DateCreated;
var rowsAffected = cmd.ExecuteNonQuery();
}
products.Clear();
}
}
}
}
I think you want something like this:
for (int i = 0; i < competitorList.Count; i++)
{
cmd.Parameters["#CompetitorID"].Value = competitorList[i];
cmd.Parameters["#ProductCode"].Value = productCodeList[i];
cmd.Parameters["#ProductName"].Value = productNameList[i];
// etc
int rowsAffected = cmd.ExecuteNonQuery();
}
Having them in a separate list like that, makes it really hard to identify which productCode goes with which productName.
I would suggest to build a dto to handle this. Something like:
public class Products
{
public string productCodeList {get; set;}
public string productNameList {get; set;}
public string productPriceList {get; set;}
public int competitorList {get; set;}
public DateTime dateCreatedList {get; set;}
}
than you can use:
List<Products> products = new List<Products>();
Alternatively you could just build the whole DataTable in your code and use SqlBulckCopy to insert it into your database.
DatTable
Quick Example of Datatables
SqlBulkCopy
I have the following method in DAL which accepts the model OrderList and returns a List<OrderList>
public List<OrderList> GetOrderList(OrderList orderList)
{
...
return new List<OrderList>();
}
When I analyze using FXCop, it's saying DoNotExposeGenericLists Error
FXCop is saying this as resolution
"Change 'List<OrderList>' in 'OrderRelatedDataAccess.GetOrderList(OrderList)' to use
Collection<T>, ReadOnlyCollection<T> or KeyedCollection<K,V>"
How can I correct this?
My OrderList model is shown below
public int serialNumber { get; set; }
public int orderID { get; set; }
public int orderListID { get; set; }
public int productID { get; set; }
public int quantity { get; set; }
public long price { get; set; }
public string productName { get; set; }
Thanks.
Edit:
Code inside the method
List<OrderList> listOfOrderList = new List<OrderList>();
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand("sGetOrderListByOrderID", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#orderID", orderList.orderID);
connection.Open();
reader = command.ExecuteReader();
int sno = 0;
while (reader.Read())
{
long price = long.Parse(reader[4].ToString());
listOfOrderList.Add(new OrderList()
{
serialNumber = ++sno,
orderID = (int)reader[0],
productID = (int)reader[2],
quantity = (int)reader[3],
price = price,
productName = reader[5].ToString(),
});
}
connection.Close();
}
return listOfOrderList;
In your case its best to change the method signature to use an IList instead of List
public IList<OrderList> GetOrderList(OrderList orderList)
{
//get your data and build your list here
return new List<OrderList>();
}
See the differences between ICollection and IList in this answer
The answer is right there in the FxCop message. Just change the return type to be ICollection<OrderList>, like so:
public ICollection<OrderList> GetOrderList(OrderList orderList)
{
...
return new List<OrderList>();
}
How can I get the results from my data reader into a List<String>?
Here is my code so far:
public List<string> Item_Getall()
{
List<string> data = new List<string>();
SqlCommand cmd = new SqlCommand("c_get_all_item",oo.conn);
cmd.CommandType = CommandType.StoredProcedure;
oo.conn.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
data.Add(rdr["item_name_id_pk"].ToString());
data.Add(rdr["item_name_arabic"].ToString());
data.Add(rdr["item_componant"].ToString());
data.Add(rdr["item_componant_arabic"].ToString());
data.Add(rdr["item_price"].ToString());
data.Add(rdr["item_image"].ToString());
data.Add(rdr["item_category_name_id_fk"].ToString());
}
oo.conn.Close();
return data;
}
You better use your custom type list instead of string and store your custom type object in list
List<YourCustomType> data = new List<YourCustomType>();
Custom type
public class YourCustom
{
public string ItemName {get; set;}
//Similarly all the properties.
}
Reading values from data Reader and adding in Custom Type List
while (rdr.Read())
{
data.Add(new YourCustom()
{
Id = rdr["item_name_id_pk"].ToString(),
Name = rdr["item_name_arabic"].ToString()
//Similarly all other properties could be set
}
}
I think you will want to create a custom class and return a list of this class:
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
Reading would go as:
var data = new List<Item>();
while (rdr.Read())
{
data.Add(new Item()
{
Id = int.Parse(rdr["item_name_id_pk"]),
Name = rdr["item_name_arabic"].ToString()
}
}
return data;
Also, look into the using() statement which will make your code more robust in the eye of exceptions during database calls.
Using a DataAdapter and a custom type:
SqlCommand cmd = new SqlCommand("c_get_all_item",oo.conn);
cmd.CommandType = CommandType.StoredProcedure;
oo.conn.Open();
var adapter = new SqlDataAdapter(cmd);
DataTable dt;
adapter.Fill(dt);
oo.Close()
//Convert DataTable to a list of YourType
List<YourType> data = dt.AsEnumerable().Select(s=>
new YourType {
item_name_id_pk = s.Field<FieldDataType>("item_name_id_pk"),
item_name_arabic = s.Field<FieldDataType>("item_name_arabic"),
...
})
.ToList();
Your custom type would be like;
public class YourType
{
//Replace the DataType with correct datatype to match with FieldDataType
public DataType item_name_id_pk {get; set;}
public DataType item_name_arabic {get; set;}
...
}