I am Newbie to ASP.NET, created the MVC Framework Web API which accepts the array of ID's as input parameter and queries the Oracle DB, this should return the result in the JSON format.Our query is like
SELECT STCD_PRIO_CATEGORY_DESCR.DESCR AS CATEGORY,
STCD_PRIO_CATEGORY_DESCR.SESSION_NUM AS SESSION_NUMBER,
Trunc(STCD_PRIO_CATEGORY_DESCR.START_DATE) AS SESSION_START_DATE
from STCD_PRIO_CATEGORY
where STCD_PRIO_CATEGORY_DESCR.STD_REF IN(X,Y,Z)
where X,Y,Z are the values we will be passing as input parameters
I created the API controller as
public class PDataController : ApiController
{
public HttpResponseMessage Getdetails([FromUri] string[] id)
{
List<OracleParameter> prms = new List<OracleParameter>();
string connStr = ConfigurationManager.ConnectionStrings["PDataConnection"].ConnectionString;
using (OracleConnection dbconn = new OracleConnection(connStr))
{
var inconditions = id.Distinct().ToArray();
var srtcon = string.Join(",", inconditions);
DataSet userDataset = new DataSet();
var strQuery = #"SELECT STCD_PRIO_CATEGORY_DESCR.DESCR AS CATEGORY,
STCD_PRIO_CATEGORY_DESCR.SESSION_NUM AS SESSION_NUMBER,
Trunc(STCD_PRIO_CATEGORY_DESCR.START_DATE) AS SESSION_START_DATE
from STCD_PRIO_CATEGORY
where STCD_PRIO_CATEGORY_DESCR.STD_REF IN(";
StringBuilder sb = new StringBuilder(strQuery);
for(int x = 0; x < inconditions.Length; x++)
{
sb.Append(":p" + x + ",");
OracleParameter p = new OracleParameter(":p" + x,OracleDbType.NVarchar2);
p.Value = inconditions[x];
prms.Add(p);
}
if(sb.Length > 0) sb.Length--;
strQuery = sb.ToString() + ")";
using (OracleCommand selectCommand = new OracleCommand(strQuery, dbconn))
{
selectCommand.Parameters.AddRange(prms.ToArray());
using (OracleDataAdapter adapter = new OracleDataAdapter(selectCommand))
{
DataTable selectResults = new DataTable();
adapter.Fill(selectResults);
var returnObject = new { data = selectResults };
var response = Request.CreateResponse(HttpStatusCode.OK, returnObject, MediaTypeHeaderValue.Parse("application/json"));
ContentDispositionHeaderValue contentDisposition = null;
if (ContentDispositionHeaderValue.TryParse("inline; filename=ProvantisStudyData.json", out contentDisposition))
{
response.Content.Headers.ContentDisposition = contentDisposition;
}
return response;
}}}}}}
It works perfectly and returns the result as
{"data":[{"CATEGORY":"Internal Study","SESSION_NUMBER":7,"SESSION_START_DATE":"2015-02-13T00:00:00"}]}
But would like to implement the entity framework here by using the Model and the DBContext.I created the model class and the DataContext Class as follows
namespace PSData.Models
{ public class StudyDataModel
{ [Key]
public string CATEGORY { get; set; }
public int SESSION_NUMBER { get; set; }
public DateTime SESSION_START_DATE { get; set; }
}}
And
namespace PSData.Models
{
public class StudyDataContext:DbContext
{
public DbSet<StudyDataModel> details { get; set; }
}}
I am not sure how to implement them in the controller. When I tried to create the Controller using Web API 2 Controller with actions,using Entity Framework selected both the Model Class and the DB Context Class it creates controller with
private StudyDataContext db = new StudyDataContext();
// GET: api/StdData
public IQueryable<StudyDataModel> Getdetails()
I am not sure how to proceed as the return type is the HttpResponseMessage in my other Controller where I am returning the JSON message. Any help is greatly appreciayed
You do not need to explicitly convert it to json format. The content negotiation module and media formatter will take care of converting the data to the needed format (XML/JSON) based on the request. By default it returns JSON.
Assuming you have a DTO class like this
public class CategoryDto
{
public string Category { get; set; }
public int SessionNumber { get; set; }
public DateTime SessionStartDate { get; set; }
}
and in your action method, you can use Request.CreateResponse method.
public HttpResponseMessage Get()
{
var db = new StudyDataContext();
var data = db.details.Select(x => new CategoryDto {
Category = x.Category,
SessionStartDate = x.SessionStartDate,
SessionNumber = x.SessionNumber }
).ToList();
return Request.CreateResponse(HttpStatusCode.OK, data);
}
Related
The list returns in api. I don't get an error if there are multiple values in the database. Returns to the list correctly. but when i get a single value i get error when using api.
Thats my code;
WebService1.asmx
[WebMethod(EnableSession = true)]
public List<AP_City> AA_Send_CountryCode(string us, string ps, string country_code)
{
AP_City menuclass = new AP_City();
List<AP_City> menuliste = new List<AP_City>();
DbClassSQL db = new DbClassSQL();
DataTable dt2x = db.Doldur("SELECT * FROM AP_City where CountyCode='" + country_code + "' order by OrderNumber");
if (dt2x.Rows.Count > 0)
{
for (int i = 0; i < dt2x.Rows.Count; i++)
{
menuclass.Id = Convert.ToInt32(dt2x.Rows[i]["Id"]);
menuliste.Add(menuclass);
menuclass = new AP_City();
}
}
return menuliste;
}
That's my class
namespace Deneme
{
public class AP_City
{
public int Id { get; set; }
}
}
Change following lines:
menuclass.Id = Convert.ToInt32(dt2x.Rows[i]["Id"]);
menuliste.Add(menuclass);
menuclass = new AP_City();
to:
menuliste.Add(new AP_City() {Id = Convert.ToInt32(dt2x.Rows[i]["Id"])});
And delete the line:
AP_City menuclass = new AP_City();
How can I convert BestellingAantal ToString because I get an error whats says cannot convert type string to bool even I made it a int? It is for a loginsystem with C#
String strSQL;
strSQL =
"SELECT BestellingId, BestellingProductId, BestellingAantal " +
"FROM bestellingen";
oCommand = new MySqlCommand(strSQL, oConnection);
oDataReader = oCommand.ExecuteReader();
//De gegevens staan per record/rij in object DataReader
//Controleer of er data bestaat alvorens verder te gaan
if (oDataReader.HasRows)
{
//lees rij per rij uit DataReader object
//oDataReader.Read krijgt de waarde False,
// indien er geen record meer is
while (oDataReader.Read())
{
int BestellingId = (int)oDataReader["BestellingId"];
int BestellingProductId = (int)oDataReader["BestellingProductId"];
int BestellingAantal = (int)oDataReader["BestellingAantal"];
Bestelling oBestelling = new Bestelling();
oBestelling.BestellingId = BestellingId.ToString();
oBestelling.BestellingProductId = BestellingProductId.ToString();
oBestelling.BestellingAantal = BestellingAantal.ToString();
BestellingLijst.Add(oBestelling);
}
}
oConnection.Close();
if (huidigeGebruiker.HasClaim(c => c.Type == ClaimTypes.DateOfBirth))
{
String Email = String.Parse(huidigeGebruiker.Claims.FirstOrDefault(c => c.Type == ClaimTypes.).Value);
}
return BestellingLijst;
}
}
}
Are you averse to using Dapper? It's a great micro ORM that lets you carry on writing SQL, but do away with all this tedious crap of reading and casting things with datareaders, opening and closing conenctions etc.. you just write an SQL that maps to an object in your c# and get dapper to run the SQL and build a (list of) objects for you.. Like this:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Dapper;
using MySql.Data.MySqlClient;
using System.Security.Permissions;
public class Program
{
public static void Main()
{
string _connectionString = "Server=127.0.0.1;Database=Bestellingen;Uid=root;Pwd=pwd;";
var service = new BestellingenService(_connectionString);
var result = service.GetBestellingens();
foreach(var item in result)
{
Console.WriteLine(item.BestellingId);
}
}
}
//a class that represents the rows in your db table
public class Bestellingen
{
public int BestellingId { get; set; }
public int BestellingProductId { get; set; }
public int BestellingAantal { get; set; }
}
//a service that runs SQLs and returns you (lists of) your data mapping class
public class BestellingenService
{
private readonly MySqlConnection _conn;
public BestellingenService(string connStr)
{
_conn = new MySqlConnection(connStr);
}
public IEnumerable<Bestellingen> GetBestellingens()
{
var sql = "SELECT BestellingId, BestellingProductId, BestellingAantal FROM bestellingen";
var result = this._conn.Query<Bestellingen>(sql).ToList();
return result;
}
public Bestellingen GetBestellingenById(int bid)
{
var sql = "SELECT BestellingId, BestellingProductId, BestellingAantal FROM bestellingen WHERE id = #pBestellingId";
var result = this._conn.Query<Bestellingen>(sql, new { pBestellingId = bid }).FirstOrDefault();
return result;
}
}
I am trying to retrieve a set of data from a MySQL database in a WebAPI application and access it through HTTP request from a mobile app. Hence I created a WebApi, a RestClient class and the class where I would show the data, this is my code.
Web API
[Produces("application/json")]
[Route("api/Blog")]
public class BlogController : Controller
{
// GET: api/Blog
[HttpGet]
public IEnumerable<string> Get()
{
}
// GET: api/Blog/5
[HttpGet("{id}", Name = "GetBlogItems")]
public string Get(int id)
{
}
// POST: api/Blog
[HttpPost]
public void Post([FromBody] RetrieveDataClass value)
{
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "INSERT INTO test.blogtable (id,Telephone,CreatedSaved,Topic,Summary,Category,Body1,Body2,Body3,Body4)values('" + value.TopicSaved1 + "','" + Value.Telephone + "','" + Value.Created/Saved + "','" + value.TopicSaved1 + "','" +value.SummarySaved1 +"','" +value.CategoriesSaved1 +"','" +value.Body1 +"','" +value.Body2 +"','" +value.Body3 +"','" +value.Body4 +"');";
MySqlCommand cmd = new MySqlCommand(Query, conn);
cmd.ExecuteReader();
conn.Close();
}
// PUT: api/Blog/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{
}
// DELETE: api/ApiWithActions/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
So, in my database, I have three rows with a telephone number of +233892929292, after the filter I have to get three rows. and I would also filter to only the topic and summary column.
RestClient Class
public class BlogRestClient<T>
{
private const string WebServiceUrl = "http://localhost:57645/api/Blog/";
public async Task<List<T>> GetAsync()
{
var httpClient = new HttpClient();
var json = await httpClient.GetStringAsync(WebServiceUrl);
var taskModels = JsonConvert.DeserializeObject<List<T>>(json);
return taskModels;
}
public async Task<bool> PostAsync(T t)
{
var httpClient = new HttpClient();
var json = JsonConvert.SerializeObject(t);
HttpContent httpContent = new StringContent(json);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var result = await httpClient.PostAsync(WebServiceUrl, httpContent);
return result.IsSuccessStatusCode;
}
public async Task<bool> PutAsync(int id, T t)
{
var httpClient = new HttpClient();
var json = JsonConvert.SerializeObject(t);
HttpContent httpContent = new StringContent(json);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var result = await httpClient.PutAsync(WebServiceUrl + id, httpContent);
return result.IsSuccessStatusCode;
}
public async Task<bool> DeleteAsync(int id, T t)
{
var httpClient = new HttpClient();
var response = await httpClient.DeleteAsync(WebServiceUrl + id);
return response.IsSuccessStatusCode;
}
}
ModelData Class
public class ModelDataClass
{
public string Telephone ;
public string Created/Saved ;
public string TopicSaved1 ;
public string SummarySaved1 ;
public string CategoriesSaved1 ;
public string Body1 ;
public string Body2 ;
public string Body3 ;
public string Body4 ;
public ModelDataClass()
{
}
}
The Values for the strings in ModelDataClass are set in another class to post in MySQL database. Since that is not causing the problem in question, I have not included the code.
RetrieveDataClass
public class RetrieveDataClass
{
public string Topic ;
public string Summary ;
public RetrieveDataClass()
{
GetDataEvent();
AddBlog();
}
public void GetDataEvent()
{
BlogRestClient<ModelDataClass> restClient = new
BlogRestClient<ModelDataClass>();
await restClient.GetAsync();
}
public ObservableCollection<ModelDataClass> BlogItems = new
ObservableCollection<ModelDataClass>();
public void AddBlog()
{
BlogListView.ItemsSource = BlogItems;
}
}
Question1
How do I retrieve the data from, Mysql, to WebAPI accessed through the REST client class(It's for mobile so I have to use Http request)?
Question2
I would like to create a listView for each row I retrieve through the MySQL database. With the heading being the data in the topic column and the subheading is with the data in summary column.
Your application is designed with the Multitier Architecture pattern. As such, you need to ensure you have a separation of concerns.
The Web API will represent your presentation logic layer. It will parse the client's request, query for the data as required and format the returned data as needed.
The RetrieveClient can then handle the data access layer. It will manage access to the database, insert, update, delete as needed.
The key point here is to ensure that each layer talks to the other to perform actions and that you do not directly access the database in your presentation layer.
As such,
How to retrieve data?
In your Data Access Layer :
public class RetrieveDataClass
{
private IDbConnection connection;
public RetrieveDataClass(System.Data.IDbConnection connection)
{
// Setup class variables
this.connection = connection;
}
/// <summary>
/// <para>Retrieves the given record from the database</para>
/// </summary>
/// <param name="id">The identifier for the record to retrieve</param>
/// <returns></returns>
public EventDataModel GetDataEvent(int id)
{
EventDataModel data = new EventDataModel();
string sql = "SELECT id,Telephone,CreatedSaved,Topic,Summary,Category,Body1,Body2,Body3,Body4 WHERE id = #id";
using (IDbCommand cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
IDbDataParameter identity = cmd.CreateParameter();
identity.ParameterName = "#id";
identity.Value = id;
identity.DbType = DbType.Int32; // TODO: Change to the matching type for id column
cmd.Parameters.Add(identity);
try
{
connection.Open();
using (IDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
data.id = reader.GetInt32(reader.GetOrdinal("id"));
// TODO : assign the rest of the properties to the object
}
else
{
// TODO : if method should return null when data is not found
data = null;
}
}
// TODO : Catch db exceptions
} finally
{
// Ensure connection is always closed
if (connection.State != ConnectionState.Closed) connection.Close();
}
}
// TODO : Decide if you should return null, or empty object if target cannot be found.
return data;
}
// TODO : Insert, Update, Delete methods
}
The above will get a record from the database, and return it as an object. You can use ORM libraries such as EntityFramework or NHibernate instead but they have their own learning curve.
How to return the data?
Your client will call the WebAPI, which in turn query for the data from the data access layer.
[Produces("application/json")]
[Route("api/Blog")]
public class BlogController : Controller
{
// TODO : Move the connection string to configuration
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
// GET: api/Blog
/// <summary>
/// <para>Retrieves the given record from the database</para>
/// </summary>
/// <param name="id">Identifier for the required record</param>
/// <returns>JSON object with the data for the requested object</returns>
[HttpGet]
public IEnumerable<string> Get(int id)
{
IDbConnection dbConnection = System.Data.Common.DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
RetrieveDataClass dal = new RetrieveDataClass(dbConnection);
EventDataModel data = dal.GetDataEvent(id);
if (data != null)
{
// Using Newtonsoft library to convert the object to JSON data
string output = Newtonsoft.Json.JsonConvert.SerializeObject(data);
// TODO : Not sure if you need IEnumerable<string> as return type
return new List<string>() { output };
} else
{
// TODO : handle a record not found - usually raises a 404
}
}
// TODO : other methods
}
There are lots of other examples online on how to access the data via API. Have a look on google and review. A few that come to mind are
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-2.2&tabs=visual-studio
https://learn.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
i solved the problem.
WebApi
[Produces("application/json")]
[Route("api/Blog")]
public class BlogController : Controller
{
// GET: api/Blog
[HttpGet]
public List<BlogViews> Get()
{
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "SELECT * FROM test.blogtable where `Telephone` ='Created'";
MySqlCommand cmd = new MySqlCommand(Query, conn);
MySqlDataReader MSQLRD = cmd.ExecuteReader();
List<BlogViews> GetBlogList = new List<BlogViews>();
if (MSQLRD.HasRows)
{
while (MSQLRD.Read())
{
BlogViews BV = new BlogViews();
BV.id = (MSQLRD["id"].ToString());
BV.DisplayTopic = (MSQLRD["Topic"].ToString());
BV.DisplayMain = (MSQLRD["Summary"].ToString());
GetBlogList.Add(BV);
}
}
conn.Close();
return GetBlogList;
}
// GET: api/Blog/5
[HttpGet("{id}", Name = "GetBlogItems")]
public string Get(int id)
{
}
// POST: api/Blog
[HttpPost]
public void Post([FromBody] RetrieveDataClass value)
{
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "INSERT INTO test.blogtable (id,Telephone,CreatedSaved,Topic,Summary,Category,Body1,Body2,Body3,Body4)values('" + value.TopicSaved1 + "','" + Value.Telephone + "','" + Value.Created/Saved + "','" + value.TopicSaved1 + "','" +value.SummarySaved1 +"','" +value.CategoriesSaved1 +"','" +value.Body1 +"','" +value.Body2 +"','" +value.Body3 +"','" +value.Body4 +"');";
MySqlCommand cmd = new MySqlCommand(Query, conn);
cmd.ExecuteReader();
conn.Close();
}
// PUT: api/Blog/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{
}
// DELETE: api/ApiWithActions/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
RetriveDataClass
public class RetrieveDataClass
{
public RetrieveDataClass()
{
AddBlog();
}
public class BlogViews
{
public string id { get; set; }
public string DisplayTopic { get; set; }
public string DisplayMain { get; set; }
public ImageSource BlogImageSource { get; set; }
}
public List<BlogViews> BlogList1 = new List<BlogViews>();
public async Task< List<BlogViews>> GetBlogs()
{
BlogRestClient<BlogViews> restClient = new BlogRestClient<BlogViews>();
var BlogV = await restClient.GetAsync();
return BlogV;
}
public async void AddBlog()
{
BlogList1 = await GetBlogs();
BlogListView.ItemsSource = BlogList1;
}
}
so now i get a listview ,which contains each row from the database and each item in the listview heading is DisplayTopic and subheading is DisplayMain.
We created a Web API which takes a Array of ID as input parameters and queries the Oracle Database, returns the result in JSON format. If the data returned is very large it throws an OutOfMemoryException issue. So planning to add an additional query parameter, which set of columns to return data.
Instead of loading loading the entire result set in to memory currently we are before serializing it out to the HttpResponseMessage. Our query is complex and huge, which selects 45 columns.I am just giving only few of the columns here as an example in the below code,
using PSData.Models;
namespace PSData.Controllers
public class PDataController : ApiController
{
public HttpResponseMessage Getdetails([FromUri] string[] id)
{
List<OracleParameter> prms = new List<OracleParameter>();
string connStr = ConfigurationManager.ConnectionStrings["PDataConnection"].ConnectionString;
using (OracleConnection dbconn = new OracleConnection(connStr))
{
DataSet userDataset = new DataSet();
var strQuery = #"SELECT STCD_PRIO_CATEGORY_DESCR.DESCR AS CATEGORY,
STCD_PRIO_CATEGORY_DESCR.SESSION_NUM AS SESSION_NUMBER,
Trunc(STCD_PRIO_CATEGORY_DESCR.START_DATE) AS SESSION_START_DATE,
STCD_PRIO_CATEGORY_DESCR.START_DATE AS SESSION_START_TIME ,
Trunc(STCD_PRIO_CATEGORY_DESCR.END_DATE) AS SESSION_END_DATE,
STCD_PRIO_CATEGORY_DESCR.END_DATE AS SESSION_END_TIME,
Round((TO_DATE (TO_CHAR (STCD_PRIO_CATEGORY_DESCR.END_DATE, 'dd/mm/yyyy hh24:mi'),'dd/mm/yyyy hh24:mi') - TO_DATE (TO_CHAR (STCD_PRIO_CATEGORY_DESCR.START_DATE, 'dd/mm/yyyy hh24:mi'),'dd/mm/yyyy hh24:mi'))*1440)AS SESSION_DURATION_MINUTES
from STCD_PRIO_CATEGORY
where STCD_PRIO_CATEGORY_DESCR.STD_REF IN(";
var sb = new StringBuilder(strQuery);
for (int x = 0; x < inconditions.Length; x++)
{
sb.Append(":p" + x + ",");
var p = new OracleParameter(":p" + x, OracleDbType.NVarchar2);
p.Value = inconditions[x];
prms.Add(p);
}
if (sb.Length > 0) sb.Length--;
strQuery = sb.Append(")").ToString();
var returnObject = new { data = new OracleDataTableJsonResponse(connStr, strQuery, prms.ToArray()) };
var response = Request.CreateResponse(HttpStatusCode.OK, returnObject, MediaTypeHeaderValue.Parse("application/json"));
ContentDispositionHeaderValue contentDisposition = null;
if (ContentDispositionHeaderValue.TryParse("inline; filename=PSData.json", out contentDisposition))
{
response.Content.Headers.ContentDisposition = contentDisposition;
}
return response;
}
Now the api call is like
http://localhost:430/api/PData?id=JW21&id=BL02&id=AB02
I understand that there are these keywords top and skip in ODATA using IQueryable so the API call is
http://localhost:9658/api/values?$top=2&$skip=2
I am not sure how to implement the above in my approach, I created the Model class like below
namespace PSData.Models
{
public class StudyDataModel
{
[Key]
public string CATEGORY { get; set; }
public int SESSION_NUMBER { get; set; }
public DateTime SESSION_START_DATE { get; set; }
public DateTime SESSION_START_TIME { get; set; }
public Nullable<DateTime> SESSION_END_DATE { get; set; }
public Nullable<DateTime> SESSION_END_TIME { get; set; }
public string DOSE_ACTIVITY { get; set; }
public Nullable<decimal> SESSION_DURATION_MINUTES { get; set; }
}
}
And
namespace PSData.Models
{
public class StudyDataContext:DbContext
{
public DbSet<StudyDataModel> details { get; set; }
}
}
But I am not sure how to implement them in my actual controller. Any help with this greatly appreciated.
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.