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;
Related
I am working on a Web API in C# and am getting my data from a SQL Database. The Get method returns all rows of (student) data, however even when I put a single student number in the GET call, it still returns all rows of data instead of a single row for the specified student. In my Roles Class I have;
public class Roles
{
List<Roles> studentRoles = new List<Roles>();
public string UserName { get; set; }
public string PersonName { get; set; }
public string Profile { get; set; }
public string Level { get; set; }
public int Year { get; set; }
public string Department { get; set; }
}
public class readRoles : Roles
{
public readRoles(DataRow dataRow)
{
UserName = (string)dataRow["UserName"];
PersonName = (string)dataRow["PersonName"];
Profile = (string)dataRow["Profile"];
Level = (string)dataRow["Level"];
Year = Convert.ToInt32(dataRow["Year"]);
Department = (dataRow["Department"] == DBNull.Value) ? "No Department" : dataRow["Department"].ToString();
}
public string UserName { get; set; }
public string PersonName { get; set; }
public string Profile { get; set; }
public string Level { get; set; }
public int Year { get; set; }
public string Department { get; set; }
}
In my Controller I have this;
List<Roles> studentRoles = new List<Roles>();
private SqlDataAdapter _adapter;
public IEnumerable<Roles> Get()
{
//Create link to database
string connString;
SqlConnection con;
connString = #"XXX";
DataTable _dt = new DataTable();
con = new SqlConnection(connString);
con.Open();
var sql = "some sql here";
SqlCommand CMD = new SqlCommand();
CMD.Connection = con;
CMD.CommandText = sql;
CMD.CommandType = System.Data.CommandType.Text;
SqlDataReader dr = CMD.ExecuteReader();
_adapter = new SqlDataAdapter
{
SelectCommand = new SqlCommand(sql, con)
};
_adapter.Fill(_dt);
List<Roles> roles = new List<Roles>(_dt.Rows.Count);
if (_dt.Rows.Count > 0)
{
foreach (DataRow studentrole in _dt.Rows)
{
roles.Add(new readRoles(studentrole));
}
}
return roles;
}
The above returns all the data as it should. To return a single row of data, I have the below Method but it still returns every single row instead of the row for the specified one when I do e.g. https://localhost:XXXXX/custom-roles-api/campusCustomRoles/12345;
[HttpGet]
public IHttpActionResult Get(string userName)
{
string connString;
SqlConnection con;
connString = #"XXX";
DataTable _dt = new DataTable();
con = new SqlConnection(connString);
con.Open();
var sql = "select distinct .... where student_reference = " + userName +;
SqlCommand CMD = new SqlCommand();
CMD.Connection = con;
CMD.CommandText = sql;
CMD.CommandType = System.Data.CommandType.Text;
SqlDataReader dr = CMD.ExecuteReader();
_adapter = new SqlDataAdapter
{
SelectCommand = new SqlCommand(sql, con)
};
_adapter.Fill(_dt);
List<Roles> roles = new List<Roles>(_dt.Rows.Count);
if (_dt.Rows.Count > 0)
{
foreach (DataRow studentrole in _dt.Rows)
{
roles.Add(new readRoles(studentrole));
}
}
var singlestu = roles.FirstOrDefault(e => e.UserName == userName);
return Ok(singlestu)
;
}
In the above example, I expect only data for student 12345 to be returned, but alas, all records are retrieved. In my WebConfig file, I have a custom Route like so;
public static void Register(HttpConfiguration config)
{
// Web API routes
// This is the original Route
//config.MapHttpAttributeRoutes();
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{Controller}/{id}",
// //routeTemplate: "api/{controller}/{action}/{id}",
// defaults: new { id = RouteParameter.Optional }
//);
// Custom Route
config.MapHttpAttributeRoutes();
// Define route
System.Web.Http.Routing.IHttpRoute rolesRoute = config.Routes.CreateRoute("custom-roles-api/{controller}/{id}",
new { id = RouteParameter.Optional }, null);
// Add route
config.Routes.Add("DefaultApi", rolesRoute);
}
Not sure where I have gone wrong and would be grateful for any pointers.
Many thanks in advance.
EDIT: As requested, please see below code when I used parameters;
[HttpGet]
public IHttpActionResult Get(string userName)
{
string connString;
SqlConnection con;
connString = #"XXXX";
DataTable _dt = new DataTable();
con = new SqlConnection(connString);
con.Open();
var sql = "select distinct .... where student_reference =#UserName " +
"and department ='LAW' " +;
SqlParameter param = new SqlParameter();
param.ParameterName = "#UserName";
param.Value = UserName;
SqlCommand CMD = new SqlCommand();
CMD.Connection = con;
CMD.CommandText = sql;
CMD.CommandType = System.Data.CommandType.Text;
SqlDataReader dr = CMD.ExecuteReader();
_adapter = new SqlDataAdapter
{
SelectCommand = new SqlCommand(sql, con)
};
_adapter.Fill(_dt);
List<Roles> roles = new List<Roles>(_dt.Rows.Count);
if (_dt.Rows.Count > 0)
{
foreach (DataRow studentrole in _dt.Rows)
{
roles.Add(new readRoles(studentrole));
}
}
var singlestu = roles.FirstOrDefault(e => e.UserName == userName);
return Ok(singlestu)
;
}
After much head-cracking, I go it to work by converting the UserName to type int in the Roles class and the source query.
There is large data in sql server database and i have made an api to read record. i used data reader to read all the data, when i test the data with google chrome, it said out of memory in te chrome and i want to use data set to control these data. how can i add data set into data reader or i need change to data table to use data set in my code? or are there any other solution to control large amount data.
my code:
public IHttpActionResult Get()
{
List<TestClass> draft = new List<TestClass>();
string mainconn = ConfigurationManager.ConnectionStrings["myconn"].ConnectionString;
SqlConnection sqlconn = new SqlConnection(mainconn);
string sqlquery = "SELECT UserID, Name, Mobile, Age, Date From tbluser";
sqlconn.Open();
SqlCommand sqlcomm = new SqlCommand(sqlquery, sqlconn);
SqlDataReader sdr = sqlcomm.ExecuteReader();
while (sdr.Read())
{
draft.Add(new TestClass()
{
UserId = sdr.GetString(0),
Name = sdr.IsDBNull(1) ? string.Empty : sdr.GetString(1),
Mobile = sdr.IsDBNull(2) ? string.Empty : sdr.GetString(2),
Age = (sdr.GetValue(3) !=DBNull.Value)? Convert.ToInt32(sdr.GetValue(3)) : 0,
Date = (sdr.GetValue(4) !=DBNull.Value)? Convert.ToDateTime(sdr.GetValue(4)): (DateTime?)null
});
}
return Ok(draft);
}
my class:
public class TestClass
{
public string UserId { get; set; }
public string Name { get; set; }
public string Mobile { get; set; }
public int Age { get; set; }
public DateTime? Date { get; set; }
}
When any process gets triggered, a separate virtual space is assigned to that process. Any program deals with virtual space not with physical memory, Garbage Collector deals with the same virtual memory to allocate and de-allocate memory.
out of memory happens due to virtual space is full
I would try in this way:
int limit = 50 // limit for data to get from DB.
public IHttpActionResult Get(int offset)
{
List<TestClass> draft = new List<TestClass>();
string mainconn = ConfigurationManager.ConnectionStrings["myconn"].ConnectionString;
using(SqlConnection sqlconn = new SqlConnection(mainconn))
{
string sqlquery = $"SELECT UserID, Name, Mobile, Age, Date From tbluser order by UserID offset {offset} rows fetch next {limit} rows only";
sqlconn.Open();
using(SqlCommand sqlcomm = new SqlCommand(sqlquery, sqlconn))
{
using(SqlDataReader sdr = sqlcomm.ExecuteReader())
{
while (sdr.Read())
{
draft.Add(new TestClass()
{
UserId = sdr.GetString(0),
Name = sdr.IsDBNull(1) ? string.Empty : sdr.GetString(1),
Mobile = sdr.IsDBNull(2) ? string.Empty : sdr.GetString(2),
Age = (sdr.GetValue(3) != DBNull.Value)? Convert.ToInt32(sdr.GetValue(3)) : 0,
Date = (sdr.GetValue(4) != DBNull.Value)? Convert.ToDateTime(sdr.GetValue(4)): (DateTime?)null
});
}
}
}
}
return Ok(draft);
}
How to save the select data below into an array.
SqlConnection conConexao1 = clsdb.AbreBanco();
SqlCommand cmd1 = new SqlCommand("select id, tamplete1, tamplete2 from usuarios ", conConexao1);
SqlDataReader dr1 = cmd1.ExecuteReader();
if (dr1.HasRows == true)
{
if (dr1.Read())
{
id = int.Parse(dr1[0].ToString());
templete1 = (dr1[1].ToString());
templete2 = (dr1[2].ToString());
}
}
I have already tried using foreach, but always passes the last table data.
As a collection, List provide better flexibility than array.
The collection should be created outside the loop and the element should be added inside the loop.
List<Usuarios> list = new List<Usuarios>();
using (SqlConnection conConexao1 = clsdb.AbreBanco())
using (SqlCommand cmd1 = new SqlCommand(
"select id, tamplete1, tamplete2 from usuarios ", conConexao1))
using (SqlDataReader dr1 = cmd1.ExecuteReader())
{
while (dr1.Read())
{
list.Add(new Usuarios
{
Id = dr1.GetInt32(0),
Templete1 = dr1[1].ToString(),
Templete2 = dr1[2].ToString()
});
}
}
The class to imitate your data structure
public class Usuarios
{
public int Id { get; set; }
public string Templete1 { get; set; }
public string Templete2 { get; set; }
}
if for some reason, you have to use an array as collection
Usuarios[] array = list.ToArray();
I have tried display data from spesific column ListView in C# and it was successfull. But I couldn't display it into spesific column in GridControl DevExpress.
This my code in ListView:
OracleCommand cmd = new OracleCommand();
OracleDataReader dr;
cmd.CommandText = #"SELECT * FROM PERMOHONANDETAIL WHERE PERMOHONANFK = '" + buka.txtID.Text + "'";
cmd.Connection = koneksi_manual.con;
dr = cmd.ExecuteReader();
while (dr.Read())
{
ListViewItem list = new ListViewItem(dr["PEKERJAAN"].ToString());
list.SubItems.Add(dr["KODEPEKERJAAN"].ToString());
list.SubItems.Add(dr["PEKERJAAN"].ToString());
list.SubItems.Add(dr["JOBFORM"].ToString());
list.SubItems.Add(dr["QTYORDER"].ToString());
list.SubItems.Add(dr["TARGETPERHARI"].ToString());
list.SubItems.Add(Convert.ToDateTime(dr["TANGGALSTART"]).ToString("dd/MM/yyyy"));
list.SubItems.Add(Convert.ToDateTime(dr["TANGGALEND"]).ToString("dd/MM/yyyy"));
list.SubItems.Add(dr["DURASIHARI"].ToString());
list.SubItems.Add(dr["NOTES"].ToString());
buka.listView1.Items.Add(list);
}
dr.Close();
buka.Focus();
buka.ShowDialog();
How can I do it into spesific column GridControl in DevExpress?
How can I solve this??
You can create a class for your rows and use the List<YourClass> as DataSource for your GridControl.
For example, you can create this class:
public class GridControlItem
{
public string KODEPEKERJAAN { get; set; }
public string PEKERJAAN { get; set; }
public string JOBFORM { get; set; }
public string QTYORDER { get; set; }
public string TARGETPERHARI { get; set; }
public string TANGGALSTART { get; set; }
public string TANGGALEND { get; set; }
public string DURASIHARI { get; set; }
public string NOTES { get; set; }
}
And use it in your GridControl as follows:
OracleCommand cmd = new OracleCommand();
OracleDataReader dr;
cmd.CommandText = #"SELECT * FROM PERMOHONANDETAIL WHERE PERMOHONANFK = '" + buka.txtID.Text + "'";
cmd.Connection = koneksi_manual.con;
dr = cmd.ExecuteReader();
var list = new List<GridControlItem>();
while (dr.Read())
{
var item = new GridControlItem();
item.KODEPEKERJAAN = dr["KODEPEKERJAAN"].ToString();
item.PEKERJAAN = dr["PEKERJAAN"].ToString();
item.JOBFORM = dr["JOBFORM"].ToString();
item.QTYORDER = dr["QTYORDER"].ToString();
item.TARGETPERHARI = dr["TARGETPERHARI"].ToString();
item.TANGGALSTART = Convert.ToDateTime(dr["TANGGALSTART"]).ToString("dd/MM/yyyy");
item.TANGGALEND = Convert.ToDateTime(dr["TANGGALEND"]).ToString("dd/MM/yyyy");
item.DURASIHARI = dr["DURASIHARI"].ToString();
item.NOTES = dr["NOTES"].ToString();
list.Add(item)
}
dr.Close();
gridControl1.DataSource = list;
Hi I have got two methods are returning two different return type of values like int and string and I am executing query inside the method with passing different variables like the below
METHOD 1
private string SelectTransactionHistory(int transactionId, ContextObject contextObject)
{
SqlConnection con;
SqlCommand cmd;
con = new SqlConnection(contextObject.ConnectionString);
con.Open();
string returnvalue = string.Empty;
string selecteQuery = "SELECT Comments
From dbo.TransactionHistory
WHERE TransactionID = '" + transactionId + "'";
cmd = new SqlCommand(selecteQuery, con);
returnvalue = (string)cmd.ExecuteScalar();
con.Close();
return returnvalue;
}
METHOD 2
private int SelectTransactionHistoryID(string comment, ContextObject contextObject)
{
SqlConnection con;
SqlCommand cmd;
con = new SqlConnection(contextObject.ConnectionString);
con.Open();
string query = "SELECT TransactionID
From dbo.TransactionHistory
WHERE Comments = '" + comment + "'";
cmd = new SqlCommand(query, con);
int returnvalue = (int)cmd.ExecuteScalar();
con.Close();
return returnvalue;
}
I am calling these methods in another method like this
int transactionId = SelectTransactionHistoryID(comment, GetContext());
string commentsreturnValue = SelectTransactionHistory(transactionId, GetContext());
how can i combine these two methods to make more generic type..
Would any one have any suggestions on how to do this..
Many Thanks.....
You could create a method to execute any query using ado.net, for sample:
private static T ExecuteQuery<T>(ContextObject contextObject, string query)
{
T result;
using (SqlConnection con = con = new SqlConnection(contextObject.ConnectionString))
{
try
{
con.Open();
using (SqlCommand cmd = cmd = new SqlCommand(query, con))
{
result = (T)cmd.ExecuteScalar();
}
}
catch
{
result = null;
}
finally
{
con.Close();
}
}
returnr result;
}
And pass a query that return a single value (in sql we use TOP 1), something like this:
var resultComment = ExecuteQuery<string>("SELECT TOP 1 Comments From dbo.TransactionHistory WHERE TransactionID = '" + transactionId + "'");
var resultTransactionId = ExecuteQuery<int>("SELECT TOP 1 TransactionID From dbo.TransactionHistory WHERE Comments = '" + comment + "'")
I have all of my infrastructure classes setup to utilize Dapper. However you can replace the dapper extension method with a regular method.
Base Service:
public interface IService
{
T Execute<T>(Func<IDbConnection, T> query);
void Execute(Action<IDbConnection> query);
}
public sealed class Service : IService
{
private readonly string _connectionString;
public Service(string connectionString)
{
_connectionString = connectionString;
}
private IDbConnection CreateConnection()
{
var connection = new SqlConnection(_connectionString);
connection.Open();
return connection;
}
public T Execute<T>(Func<IDbConnection, T> query)
{
using (var connection = CreateConnection())
{
return query(connection);
}
}
public void Execute(Action<IDbConnection> query)
{
using (var connection = CreateConnection())
{
query(connection);
}
}
}
DTO:
public class TransactionHistory
{
public int TransactionID { get; set; }
public string Comments { get; set; }
}
Service:
public interface ITransactionHistoryService
{
IEnumerable<TransactionHistory> GetByTransactionId(int transactionId);
IEnumerable<TransactionHistory> GetByComment(string comment);
}
public sealed class TransactionHistoryService : ITransactionHistoryService
{
// Note SELECT * is frowned upon. Replace with actual column names.
private const string GetByTransactionIdQuery =
"SELECT * FROM dbo.TransactionHistory WHERE TransactionID = #TransactionId";
private const string GetByCommentQuery =
"SELECT * FROM dbo.TransactionHistory WHERE Comments = #Comment";
private readonly IService _service;
public TransactionHistoryService(IService service)
{
_service = service;
}
public IEnumerable<TransactionHistory> GetByTransactionId(int transactionId)
{
var result = _service.Execute(c =>
c.Query<TransactionHistory>(GetByTransactionIdQuery,
new { TransactionId = transactionId }));
return result;
}
public IEnumerable<TransactionHistory> GetByComment(string comment)
{
var result = _service.Execute(c =>
c.Query<TransactionHistory>(GetByCommentQuery,
new { Comment = comment }));
return result;
}
}
You can create a single function as follows- (Not tested)
private string[] SelectTransactionHistory(int transactionId, ContextObject contextObject)
{
string[] returnValues;
SqlConnection con;
SqlCommand cmd;
SqlDataReader reader;
con = new SqlConnection(contextObject.ConnectionString);
con.Open();
string returnvalue = string.Empty;
string selecteQuery = "SELECT TransactionID, Comments From dbo.TransactionHistory WHERE TransactionID = '" + transactionId + "'";
cmd = new SqlCommand(selecteQuery, con);
reader = cmd.ExecuteReader();
while(reader.Read())
{
returnValues[0] = reader["TransactionID"].ToString();
returnValues[1] = reader["Comments"].ToString();
}
con.Close();
return returnValues;
}
And then call it as follows-
string[] TransactionHistory = SelectTransactionHistory(transactionId, GetContext());
int transactionId = Convert.ToInt32(TransactionHistory[0]);
string commentsreturnValue = TransactionHistory[1];
The above code is not tested. But you can get an idea.