For importing an Excel sheet in SQL Table I used this code, it uses SqlBulkCopy.
How can I Remove the mapper class and create the columns dynamically?
using SQL;
namespace Reader
{
Public partial class Form1 :Form
{
/// <summary>
/// Import Excel document into the SQL Database and Datagridview
/// </summary>
private void ImportExcel_Click(object sender, EventArgs e)
{
try
{
using (OpenFileDialog ImportExcelFileDialog = new OpenFileDialog() { Filter = "Excel Workbook|*.xlsx|Excel 97 -2003 Workbook|*.xls" })
{
if (ImportExcelFileDialog.ShowDialog() == DialogResult.OK)
{
using (var stream = File.Open(ImportExcelFileDialog.FileName, FileMode.Open, FileAccess.Read))
{
using (IExcelDataReader Reader = ExcelReaderFactory.CreateReader(stream))
{
DataSet result = Reader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = (_) => new ExcelDataTableConfiguration() { UseHeaderRow = true }
});
SqlConnection Connection = new SqlConnection(SQL_Commands._Connectionstring);
Connection.Open();
//SqliteDatabase[3] will give the table name that is used in SQLExpress
sqlcommands.DeleteTable(SqliteDatabase[3]);
//this is created from a SQL Query file there is only one column and that is ID
sqlcommands.RecreateDatabase(Connection);
//Get result from Excel file and create a Table from it.
tableCollection = result.Tables;
DataTable dt = tableCollection[SqliteDatabase[3]];
//Create columns in SQL Database
foreach(DataColumn column in dt.Columns)
{
if(column.ColumnName != "ID")
{
string columnName = "[" + column.ColumnName + "]";
sqlcommands.AddColumn(columnName, SQLite.SqliteDatabase[3], "Text");
}
}
//write already the values to datagridview
InstrumentsBindingSource.DataSource = dt;
//Convert Datatable to IEnumerable(Instruments is a Mapper class)
var parts = BulkHelper.DataTableToIEnumerable<Instruments>(dt);
sqlcommands.ImportToExcel(parts, Connection);
sqlcommands.UpdateTableTotal(SQLite.SqliteDatabase[3], InstrumentsBindingSource, dataGridView1);
}
}
}
}
}
catch (Exception EX)
{
MessageBox.Show(EX.ToString(), "Import Excel Sheet", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
}
Convert DataTable to IEnumerable
namespace SQL
{
public static class BulkHelper
{
public static IEnumerable<T> DataTableToIEnumerable<T>(this DataTable table) where T : class, new()
{
try
{
var objType = typeof(T);
ICollection<PropertyInfo> properties;
lock (_Properties)
{
if (!_Properties.TryGetValue(objType, out properties))
{
properties = objType.GetProperties().Where(property => property.CanWrite).ToList();
_Properties.Add(objType, properties);
}
}
var list = new List<T>(table.Rows.Count);
foreach (var row in table.AsEnumerable().Skip(1))
{
var obj = new T();
foreach (var prop in properties)
{
try
{
var propType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
var SafeValue = row[prop.Name] == null ? null : Convert.ChangeType(row[prop.Name], propType);
prop.SetValue(obj, SafeValue, null);
}
catch
{
// ignored
}
}
list.Add(obj);
}
return list;
}
catch
{
return Enumerable.Empty<T>();
}
}
}
}
Create BulkData and write it to SQL Table
namespace SQL
{
public class SQL_Commands
{
public void ImportToExcel(IEnumerable<Instruments> Parts, SqlConnection connection)
{
try
{
var bulkcopy = new SqlBulkCopy(connection);
bulkcopy.DestinationTableName = "Instruments";
bulkcopy.ColumnMappings.Add("Tag", "Tag");
bulkcopy.ColumnMappings.Add("Area", "Area");
bulkcopy.ColumnMappings.Add("Number", "Number");
bulkcopy.ColumnMappings.Add("Tag_Name", "Tag_Name");
bulkcopy.ColumnMappings.Add("Component_Description", "Component_Description");
bulkcopy.ColumnMappings.Add("Function", "Function");
bulkcopy.ColumnMappings.Add("Brand", "Brand");
bulkcopy.ColumnMappings.Add("Type", "Type");
bulkcopy.ColumnMappings.Add("M_Connection", "M_Connection");
bulkcopy.ColumnMappings.Add("E_Connection", "E_Connection");
bulkcopy.ColumnMappings.Add("Range", "Range");
bulkcopy.ColumnMappings.Add("Remark", "Remark");
bulkcopy.ColumnMappings.Add("Ordering_Code", "Ordering_Code");
bulkcopy.ColumnMappings.Add("Panel", "Panel");
bulkcopy.ColumnMappings.Add("DI", "DI");
bulkcopy.ColumnMappings.Add("DO", "DO");
bulkcopy.ColumnMappings.Add("AI", "AI");
bulkcopy.ColumnMappings.Add("AO", "AO");
bulkcopy.ColumnMappings.Add("Ethernet", "Ethernet");
bulkcopy.ColumnMappings.Add("ASI", "ASI");
using (var datareader = new ObjectDataReader<Instruments>(Parts))
{
bulkcopy.WriteToServer(datareader);
}
}
catch (Exception EX)
{
MessageBox.Show(EX.ToString(), "InsertBulk", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
}
Mapper Class
namespace SQL
{
public class Instruments
{
public string Tag { get; set; }
public string Area { get; set; }
public string Number { get; set; }
public string Tag_Name { get; set; }
public string Component_Description { get; set; }
public string Function { get; set; }
public string Brand { get; set; }
public string Type { get; set; }
public string M_Connection { get; set; }
public string E_Connection { get; set; }
public string Range { get; set; }
public string Remark { get; set; }
public string Ordering_Code { get; set; }
public string Panel { get; set; }
public string DI { get; set; }
public string DO { get; set; }
public string AI { get; set; }
public string AO { get; set; }
public string Ethernet { get; set; }
public string ASI { get; set; }
}
}
I tried to search on the web, but I could not find a good solution for it.
I changed it to this and it works. Thanks
/// <summary>
/// Import Excel document into the SQL Database and Datagridview
/// </summary>
private void ImportExcel_Click(object sender, EventArgs e)
{
try
{
using (OpenFileDialog ImportExcelFileDialog = new OpenFileDialog() { Filter = "Excel Workbook|*.xlsx|Excel 97 -2003 Workbook|*.xls" })
{
if (ImportExcelFileDialog.ShowDialog() == DialogResult.OK)
{
using (var stream = File.Open(ImportExcelFileDialog.FileName, FileMode.Open, FileAccess.Read))
{
using (IExcelDataReader Reader = ExcelReaderFactory.CreateReader(stream))
{
DataSet result = Reader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = (_) => new ExcelDataTableConfiguration() { UseHeaderRow = true }
});
SqlConnection Connection = new SqlConnection(SQL_Commands._Connectionstring);
Connection.Open();
sqlcommands.DeleteTable(SqliteDatabase[3]);
//this is created from a SQL Query file there is only one column and that is ID
sqlcommands.RecreateDatabase(Connection);
//Get result from Excel file and create a Table from it.
tableCollection = result.Tables;
DataTable dt = tableCollection[SqliteDatabase[3]];
// Create new List
List<string> ListColums = new List<string>();
//Create columns in SQL Database
foreach(DataColumn column in dt.Columns)
{
if(column.ColumnName != "ID")
{
string columnName = "[" + column.ColumnName + "]";
sqlcommands.AddColumn(columnName, SQLite.SqliteDatabase[3], "Text");
//Add Column Names to List<string>
ListColums.Add(column.ColumnName);
}
}
//write already the values to datagridview
InstrumentsBindingSource.DataSource = dt;
//Create a connection
sqlcommands.ImportFromExcel(Connection,dt, ListColums);
sqlcommands.UpdateTableTotal(SQLite.SqliteDatabase[3], InstrumentsBindingSource, dataGridView1);
}
}
}
}
}
catch (Exception EX)
{
MessageBox.Show(EX.ToString(), "UpdateTableTotal", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
public void ImportFromExcel(SqlConnection connection,DataTable _dt,List<string> ColumnNames )
{
try
{
// Get the DataTable
DataTable dtInsertRows = _dt;
using (SqlBulkCopy bulkcopy = new SqlBulkCopy(connection.ConnectionString, SqlBulkCopyOptions.KeepIdentity))
{
bulkcopy.DestinationTableName = "Instruments";
bulkcopy.BatchSize = _dt.Rows.Count;
foreach (string Column in ColumnNames)
{
var split = Column.Split(new[] { ',' });
bulkcopy.ColumnMappings.Add(split.First(), split.Last());
}
bulkcopy.WriteToServer(dtInsertRows);
}
}
catch (Exception EX)
{
MessageBox.Show(EX.ToString(), "InsertBulk", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
Related
I am trying to make a generic method where I can insert any object into a sqlite3 database.
User class:
public class Users : IClassModel<Users>
{
public int Id { get; set; }
public string UserName { get; set; }
public string UserAddress { get; set; }
public string OtherUserDetails { get; set; }
public decimal AmountOfFine { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
}
Interface class:
public interface IClassModel<T>
{
public int Id { get; set; }
}
QueryBuilder class:
public class queryBuilder : IDisposable
{
private SqliteConnection _connection;
public queryBuilder(string connectionString)
{
_connection = new SqliteConnection(connectionString);
_connection.Open();
}
public void Dispose()
{
_connection.Close();
}
public void Create<T>(T obj) where T : IClassModel<T>
{
// insert into tableName values()
Type myType = obj.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());
ArrayList valueArray = new ArrayList();
ArrayList nameArray = new ArrayList();
var questionString = "";
var nameString = "";
foreach (PropertyInfo prop in props)
{
object propValue = prop.GetValue(obj, null);
object propName = prop.Name;
valueArray.Add(propValue);
nameArray.Add(propName);
questionString += "?, ";
nameString += $"{propName}, " ;
}
var newNameString = nameString.Trim();
var newerNameString = newNameString.TrimEnd(',');
var newQuestionString = questionString.Trim();
var newerQuestionString = newQuestionString.TrimEnd(',');
SqliteCommand insertSQL = new SqliteCommand($"INSERT INTO {typeof(T).Name} ({newerNameString}) VALUES ({newerQuestionString})", _connection);
foreach (var item in valueArray)
{
insertSQL.Parameters.Add(item);
}
insertSQL.ExecuteNonQuery();
//Console.WriteLine("Successfully added the thing.");
}
}
Driver:
using Microsoft.Data.Sqlite;
using QueryBuilder.Models;
using System.Reflection;
using (var query = new queryBuilder(#"Data Source=C:\path\to\database"))
{
// con
var user = new Users();
user.UserName = "username";
user.UserAddress = "some_address";
user.OtherUserDetails = "details";
user.AmountOfFine = 90;
user.Email = "something#email.com";
user.PhoneNumber = "5555555555";
query.Create<Users>(user);
}
I know my code is bit messy, but the idea is to somehow create an object and then be able to insert it into the already made table, no matter what object it is. I keep getting invalid cast exceptions.
I need to be able to iterate through the values and properties and add them to the sqlite insert command but it doesn't seem to be working. Any help is appreciated.
I am trying to read from a .csv file to an object array.
There are other solutions here that give solutions for lists but I cannot seem to make it work for me.
Object definition:
public class DTOClass
{
//declare data members
[DataMember]
public DateTime Date { get; set; }
[DataMember]
public string stock_symbol { get; set; }
[DataMember]
public double stock_price_open { get; set; }
[DataMember]
public double stock_price_close { get; set; }
[DataMember]
public double stock_price_low { get; set; }
[DataMember]
public double stock_price_high { get; set; }
[DataMember]
public double stock_price_adj_close { get; set; }
[DataMember]
public long stock_volume { get; set; }
[DataMember]
public string stock_exchange { get; set; }
}
Instance declaration:
private DTOClass[] _dTOs;
Filter method:
private List<DTOClass> FromCsv(string csvLine, List<DTOClass> rest)
{
DataTable _dt = new DataTable();
string[] values = csvLine.Split(',');
int j = _dt.Rows.Count;
for (int i = 0; i < j; i++)
{
DTOClass dto = new DTOClass();
dto.Date = Convert.ToDateTime(values[0]);
dto.stock_symbol = Convert.ToString(values[1]);
dto.stock_price_open = Convert.ToDouble(values[2]);
dto.stock_price_close = Convert.ToDouble(values[3]);
dto.stock_price_low = Convert.ToDouble(values[4]);
dto.stock_price_high = Convert.ToDouble(values[5]);
dto.stock_price_adj_close = Convert.ToDouble(values[6]);
dto.stock_volume = Convert.ToInt64(values[7]);
dto.stock_exchange = Convert.ToString(values[8]);
rest.Add(dto);
}
return rest;
}
Calling filter:
DTO = File.OpenText(Filename).ReadLine().Select(v => FromCsv(v.ToString(),
_restDto)).ToArray();
I need this to return to an object array because it then goes into a CollectionView on a datagrid.
But I keep getting this error:
"Cannot implicitly convert type 'System.Collections.Generic.List[]' to 'MBM.Services.DTOClass[]'"
I know that I'm obviously returning a list of a list, but I've tried other methods that are offered and I'm simply stumped.
I've also tried this:
private static DataTable GetDataTableFromCSVFile(string csv_file_path)
{
DataTable csvData = new DataTable();
try
{
using (TextFieldParser csvReader = new TextFieldParser(csv_file_path))
{
csvReader.SetDelimiters(new string[] { "," });
//csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
//Making empty value as null
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
}
csvData.Rows.Add(fieldData);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return csvData;
}
Calling with:
DataTable csvData = GetDataTableFromCSVFile(Filename);
But this doesn't seem to return anything from the file.
Any help is appreciated, thanks.
One simple way will be to split the lines and select them into your new object.
var result = File.ReadAllLines("pathTo.csv")
.Select(line => line.Split(','))
.Select(x => new MyObject {
prop1 = x[0],
prop2 = x[1],
//etc..
})
.ToArray();
There's no point in recreating the wheel, Id just use CsvHelper, it has support for what you're doing in addition to handling malformed CSV's you can additionally set up mapping like so:
public sealed class MyClassMap : ClassMap<MyClass>
{
public MyClassMap()
{
AutoMap();
Map( m => m.CreatedDate ).Ignore();
}
}
Then you can get the object like so:
var csv = new CsvReader( textReader );
var records = csv.GetRecords<MyClass>();
When I want to use the method that transmits data from the table to the list, I have the following problem.
An exception of type 'System.Reflection.TargetInvocationException' occurred in EntityFramework.dll but was not handled in user code
Additional information: Exception has been thrown by the target of an invocation.
enter image description here
This is schema my database in phpmyadmin
enter image description here
and this is schema my edmx
enter image description here
Part code of Model.cs
public partial class produkty
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public produkty()
{
this.zamowienias = new HashSet<zamowienia>();
}
public int idproduktu { get; set; }
public int idtypu { get; set; }
public string nazwa { get; set; }
public byte cena { get; set; }
public string opis { get; set; }
public byte[] image { get; set; }
public virtual typproduktu typproduktu { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<zamowienia> zamowienias { get; set; }
}
public partial class typproduktu
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public typproduktu()
{
this.produkties = new HashSet<produkty>();
}
public int idtypu { get; set; }
public string nazwa { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<produkty> produkties { get; set; }
And this code of ProductModel.cs when I want tu use method GetAllProducts and I have errors when I want running
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for ProductModel
/// </summary>
public class ProductModel
{
public string InsertProduct(produkty product)
{
try
{
komisEntities db = new komisEntities();
db.produkties.Add(product);
db.SaveChanges();
return product.nazwa + " Poprawnie wstawiono";
}
catch (Exception e)
{
return "Error:" + e;
}
}
public string UpdateProduct(int idproduktu, produkty product)
{
try
{
komisEntities db = new komisEntities();
//Fetch object from db
produkty p = db.produkties.Find(idproduktu);
p.nazwa = product.nazwa;
p.idtypu = product.idtypu;
p.cena = product.cena;
p.opis = product.opis;
p.image = product.image;
db.SaveChanges();
return product.nazwa + " was succesfully updated";
}
catch (Exception e)
{
return "Error:" + e;
}
}
public string DeleteProduct(int idproduktu)
{
try
{
komisEntities db = new komisEntities();
produkty produkt = db.produkties.Find(idproduktu);
db.produkties.Attach(produkt);
db.produkties.Remove(produkt);
db.SaveChanges();
return produkt.nazwa + "poprawnie usunięto";
}
catch (Exception e)
{
return "Error:" + e;
}
}
public produkty GetProduct(int idproduktu)
{
using (komisEntities db = new komisEntities())
{
produkty product = db.produkties.Find(idproduktu);
return product;
}
}
public List<produkty> GetAllProducts()
{
// try
// {
using (komisEntities db = new komisEntities())
{
List<produkty> products = (from x in db.produkties
select x).ToList();
return products;
}
// }
// catch (Exception ex)
// {
// return null;
// }
}
public List<produkty> GetProductsByType(int idtypu)
{
using (komisEntities db = new komisEntities())
{
List<produkty> products = (from x in db.produkties
where x.idtypu == idtypu
select x).ToList();
return products;
}
}
}
IMAGE OF ERROR:
enter image description here
WHat can i do to add products to list to Display Data Items and Details by this function
protected void Page_Load(object sender, EventArgs e)
{
FillPage();
}
private void FillPage()
{
ProductModel model = new ProductModel();
List<produkty> products = model.GetAllProducts();
if (products != null)
{
// Response.Redirect("~/Pages/Login.aspx");
foreach (produkty product in products)
{
Panel productPanel = new Panel();
ImageButton imageButton = new ImageButton
{
ImageUrl = "~/Images/Products/" + product.image,
CssClass = "productImage",
PostBackUrl = string.Format("~/Pages/Product.aspx?id={0}", product.idproduktu)
};
Label lblName = new Label
{
Text = product.nazwa,
CssClass = "productName"
};
Label lblPrice = new Label
{
Text = "£ " + product.cena,
CssClass = "productPrice"
};
productPanel.Controls.Add(imageButton);
productPanel.Controls.Add(new Literal { Text = "<br/>" });
productPanel.Controls.Add(lblName);
productPanel.Controls.Add(new Literal { Text = "<br/>" });
productPanel.Controls.Add(lblPrice);
//Add dynamic controls to static control
pnlProducts.Controls.Add(productPanel);
}
}
else
// Response.Redirect("~/Pages/About.aspx");
pnlProducts.Controls.Add(new Literal { Text = "No products found!" });
}
}
But I cant and cuz I have message "No products found!"
I believe you have a data typing issue: productky.cena is of type byte in your model but of type decimal(10,0) in your database. I don't think there's an implicit conversion between those two, hence the "Specified cast not valid" error in your screenshot.
Using Recursion I Want to Display the list of Contents to the datagridview in c# winforms.I tried by the below But as a result in datagridview Only Parent values displaying no Child Values Displayed
public class PageItem
{
public int Id { get; set; }
public int ParentId { get; set; }
public string MenuText { get; set; }
public List<PageItem> Childs { get; set; }
}
Conditions:-
public List<PageItem> GetPageItems()
{
List<PageItem> pageItems = new List<PageItem>();
SqlCeConnection conn = new SqlCeConnection(#"Data
Source=D:\database\Employee.mdf;");
SqlCeCommand cmd = new SqlCeCommand("SELECT Id, ParentId, MenuTitle
FROM Page", conn);
conn.Open();
SqlCeDataReader rdr = cmd.ExecuteReader();
var allItems = new List<PageItem>();
while (rdr.Read())
{
var item = (new PageItem()
{
Id = Convert.ToInt32(rdr["Id"]),
ParentId = Convert.ToInt32(rdr["ParentId"]),
MenuText = rdr["MenuTitle"].ToString()
});
allItems.Add(item);
var parent = allItems.Where(pi => pi.Id == item.ParentId).SingleOrDefault();
if (parent == null)
{
pageItems.Add(item);
}
else
{
if (parent.Childs == null)
parent.Childs = new List<PageItem>();
parent.Childs.Add(item);
}
}
rdr.Close();
conn.Close();
return pageItems;
}
Form Load:-
private void Form1_Load(object sender, EventArgs e)
{
GetPageItems();
this.dataGridView1.DataSource = GetPageItems();
this.comboBox1.DataSource = GetPageItems();
this.comboBox1.DisplayMember = "MenuText";
this.comboBox1.ValueMember = "ParentId";
}
From the above code I got an output like this:-
parent 0
parent 1
parent 2
parent 3
I Need an Output Like this:-
Parent 0
Child 1
Child 2
Child 3
Child 3.1
Child 3.2
Child 3.3
Parent 1
Parent 2
Parent 3
Thank You..
Finally I Got Answer For the Above Question Using Recursion .If Anybody Needs make Use of it Thank You:-
public class Student
{
public int ID { get; set; }
public int ParentID { get; set; }
public string Title { get; set; }
}
public class Parent
{
public int pID { get; set; }
public int pParentID { get; set; }
public string pTitle { get; set; }
}
public class OutPut
{
public int mID { get; set; }
public int mParentID { get; set; }
public string mTitle { get; set; }
}
public class SubOutPut
{
public int SubsmID { get; set; }
public int SubsmParentID { get; set; }
public string SubsmTitle { get; set; }
}
Form Load
public static List<SubOutPut> ChildList = new List<SubOutPut>();
private void Form3_Load(object sender, EventArgs e)
{
List<Student> std = loaddataFull();
List<Parent> prnt = loaddataParent();
List<OutPut> MenuItems = new List<OutPut>();
foreach (Parent id in prnt)
{
int pid=Convert.ToInt32(id.pID);
//Adding Parent Values to the List
List<SubOutPut> SubMenuItems = new List<SubOutPut>();
MenuItems.Add(new OutPut()
{
mID=Convert.ToInt32(id.pID),
mParentID=Convert.ToInt32(id.pParentID),
mTitle=Convert.ToString(id.pTitle),
});
SubMenuItems = GetChildrens(pid);
foreach (SubOutPut Add in SubMenuItems)
{
MenuItems.Add(new OutPut()
{
mID = Convert.ToInt32(Add.SubsmID),
mParentID = Convert.ToInt32(Add.SubsmParentID),
mTitle = Convert.ToString(Add.SubsmTitle)
});
}
SubMenuItems.Clear();
}
dataGridView1.DataSource = MenuItems;
foreach (var item in MenuItems)
{
listView1.Items.Add(item.mID.ToString());
listView1.Items.Add(item.mParentID.ToString());
listView1.Items.Add(item.mTitle.ToString());
listView1.View = View.Tile;
}
dataGridView2.DataSource = loaddataParent();
}
Loading all datas from database
public List<Student> loaddataFull()
{
List<Student> student = new List<Student>();
SqlConnection conn = new SqlConnection(#"Data Source=ADMIN-PC\SQLEXPRESS;Initial Catalog=test;Integrated Security=true");
SqlCommand cmd = new SqlCommand("select * from testing", conn);
SqlDataReader dr;
try
{
conn.Open();
dr = cmd.ExecuteReader();
while (dr.Read())
{
student.Add(new Student()
{
ID = dr.GetInt32(dr.GetOrdinal("id")),
ParentID = dr.GetInt32(dr.GetOrdinal("pid")),
Title = dr.GetString(dr.GetOrdinal("title"))
});
}
dr.Close();
}
catch (Exception exp)
{
throw;
}
finally
{
conn.Close();
}
return student;
}
Load Only The Parent Values:-
public List<Parent> loaddataParent()
{
List<Parent> parent = new List<Parent>();
SqlConnection conn = new SqlConnection(#"Data Source=ADMIN-PC\SQLEXPRESS;Initial Catalog=test;Integrated Security=true");
SqlCommand cmd = new SqlCommand("select * from testing where pid=0", conn);
SqlDataReader dr;
try
{
conn.Open();
dr = cmd.ExecuteReader();
while (dr.Read())
{
parent.Add(new Parent()
{
pID = dr.GetInt32(dr.GetOrdinal("id")),
pParentID = dr.GetInt32(dr.GetOrdinal("pid")),
pTitle = dr.GetString(dr.GetOrdinal("title"))
});
}
dr.Close();
}
catch (Exception exp)
{
throw;
}
finally
{
conn.Close();
}
return parent;
}
And Here Comes The Recursion Method:-
public string gg = " ";
public List<SubOutPut> GetChildrens(int ID)
{
List<Student> std = loaddataFull();
foreach (Student Child in std)
{
if (Child.ParentID == ID)
{
ChildList.Add(new SubOutPut()
{
SubsmID = Convert.ToInt32(Child.ID),
SubsmParentID = Convert.ToInt32(Child.ParentID),
SubsmTitle = Convert.ToString(gg + Child.Title)
});
gg = gg+gg;
GetChildrens(Child.ID);
gg = " ";
}
}
return ChildList;
}
Thank You:---
i have populated data reader from db table and i have class like
public class CandidateApplication
{
public string EmailID { get; set; }
public string Name { get; set; }
public string PhoneNo { get; set; }
public string CurrentLocation { get; set; }
public string PreferredWorkLocation { get; set; }
public int RoleApplingFor { get; set; }
public string CurrentJobTitle { get; set; }
public int EducationLevel { get; set; }
public decimal SalaryExpected { get; set; }
public string AvailableTime { get; set; }
public int AdvertID { get; set; }
public bool SignForAlert { get; set; }
public string CVInText { get; set; }
public string CVFileName { get; set; }
public bool IsDownloaded { get; set; }
public string specialization { get; set; }
public bool isallocated { get; set; }
public int id { get; set; }
public string AdvertAdditionalInfo { get; set; }
}
i can populate the above class in loop. we can iterate in data reader and populate class but i want to know is there any short cut way to populate class from data reader.
if data deserialization is possible from data reader to class then also tell me if few fields are there in class which are not there in data reader then how to handle the situation.
You don't need to use a Data Reader, You could just Populate the Data into a DataTable, and use the below method to create a List of your CandidateApplication Class.
The Call :-
List<CandidateApplication> CandidateList = GetCandidateInformation();
The Method that generates the list :-
public List<CandidateApplication> GetCandidateInformation()
{
DataTable dt = new DataTable();
using (OleDbConnection con = new OleDbConnection(ConfigurationManager.AppSettings["con"]))
{
using (OleDbCommand cmd = new OleDbCommand("SELECT * FROM [TableName]", con))
{
var adapter = new OleDbDataAdapter();
adapter.SelectCommand = cmd;
con.Open();
adapter.Fill(dt);
var CandApp = (from row in dt.AsEnumerable()
select new CandidateApplication
{
EmailID = row.Field<string>("EmailID"),
Name = row.Field<string>("Name"),
PhoneNo = row.Field<string>("PhoneNo"),
CurrentLocation = row.Field<string>("CurrentLocation"),
PreferredWorkLocation = row.Field<string>("PreferredWorkLocation"),
RoleApplingFor = row.Field<int>("RoleApplingFor"),
CurrentJobTitle = row.Field<string>("CurrentJobTitle"),
EducationLevel = row.Field<int>("EducationLevel "),
SalaryExpected = row.Field<decimal>("SalaryExpected"),
AvailableTime = row.Field<string>("AvailableTime"),
AdvertID = row.Field<int>("AdvertID"),
SignForAlert = row.Field<bool>("SignForAlert"),
CVInText = row.Field<string>("CVInText"),
CVFileName = row.Field<string>("CVFileName"),
IsDownloaded = row.Field<bool>("IsDownloaded"),
Specialization = row.Field<string>("Specialization"),
Isallocated = row.Field<bool>("Isallocated"),
Id = row.Field<int>("Id"),
AdvertAdditionalInfo = row.Field<string>("AdvertAdditionalInfo")
}).ToList();
return CandApp;
}
}
}
Although not an answer to your question, I would suggest you to consider the following workaround, which uses a SqlDataAdapter instead of a data reader:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Xml.Serialization;
class Program
{
static void Main(string[] args)
{
var cs = "YourConnectionString";
var xml = "";
using (var con = new SqlConnection(cs))
using (var c = new SqlCommand("SELECT * FROM CandidateApplication", con))
{
con.Open();
using (var adapter = new SqlDataAdapter(c))
{
var ds = new DataSet("CandidateApplications");
ds.Tables.Add("CandidateApplication");
adapter.Fill(ds, ds.Tables[0].TableName);
xml = ds.GetXml();
}
}
// We need to specify the root element
var rootAttribute = new XmlRootAttribute();
// The class to use as the XML root element (should match the name of
// the DataTable in the DataSet above)
rootAttribute.ElementName = "CandidateApplications";
// Initializes a new instance of the XmlSerializer class that can
// serialize objects of the specified type into XML documents, and
// deserialize an XML document into object of the specified type.
// It also specifies the class to use as the XML root element.
// I chose List<CandidateApplication> as the type because I find it
// easier to work with (but CandidateApplication[] will also work)
var xs = new XmlSerializer(typeof(List<CandidateApplication>), rootAttribute);
// Deserialize the XML document contained by the specified TextReader,
// in our case, a StringReader instance constructed with xml as a parameter.
List<CandidateApplication> results = xs.Deserialize(new StringReader(xml));
}
}
For those properties that are missing in the retrieved data, you could declare a private field with a default value:
string _advertAdditionalInfo = "default";
public string AdvertAdditionalInfo
{
get
{
return _advertAdditionalInfo;
}
set
{
_advertAdditionalInfo = value;
}
}
If you would like to enforce that the retrieved data will not fill in a specific property, use:
[XmlIgnoreAttribute]
public string AdvertAdditionalInfo { get; set; }
I made a generic function for converting the SELECT result from an OleDbCommand to a list of classes.
Let's say that I have a class that looks like this, which maps to the columns in the database:
internal class EconEstate
{
[Column(Name = "basemasterdata_id")]
public Guid BaseMasterDataId { get; set; }
[Column(Name = "basemasterdata_realestate")]
public Guid? BaseMasterDataRealEstate { get; set; }
[Column(Name = "business_area")]
public string BusinessArea { get; set; }
[Column(Name = "profit_centre")]
public int ProfitCentre { get; set; }
[Column(Name = "rentable_area")]
public decimal RentableArea { get; set; }
}
Then I can get a list of those EconEstate objects using this code:
public void Main()
{
var connectionString = "my connection string";
var objects = ReadObjects<EconEstate>(connectionString, "EMBLA.EconEstates").ToList();
}
private static IEnumerable<T> ReadObjects<T>(string connectionString, string tableName) where T : new()
{
using (var connection = new OleDbConnection(connectionString))
{
connection.Open();
using (var command = new OleDbCommand($"SELECT * FROM {tableName};", connection))
{
var adapter = new OleDbDataAdapter
{
SelectCommand = command
};
var dataTable = new DataTable();
adapter.Fill(dataTable);
foreach (DataRow row in dataTable.Rows)
{
var obj = new T();
foreach (var propertyInfo in typeof(T).GetProperties())
{
var columnAttribute = propertyInfo.GetCustomAttributes().OfType<ColumnAttribute>().First();
var value = row[columnAttribute.Name];
var convertedValue = ConvertValue(value, propertyInfo.PropertyType);
propertyInfo.SetValue(obj, convertedValue);
}
yield return obj;
}
}
}
}
private static object ConvertValue(object value, Type targetType)
{
if (value == null || value.GetType() == typeof(DBNull))
{
return null;
}
if (value.GetType() == targetType)
{
return value;
}
var underlyingTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType;
if (value is string stringValue)
{
if (underlyingTargetType == typeof(int))
{
return int.Parse(stringValue);
}
else if (underlyingTargetType == typeof(decimal))
{
return decimal.Parse(stringValue);
}
}
var valueType = value.GetType();
var constructor = underlyingTargetType.GetConstructor(new[] { valueType });
var instance = constructor.Invoke(new object[] { value });
return instance;
}
As you can see, the code is generic, making it easy to handle different tables and classes.