Better way to get json data from relational databases? - c#

I don't know my title is understandable but actually I want to know which one is better?
1-Creating object class and get data from mssql db with loop
2-Getting data from sql db with json format
3-Something else..
I think, loop can be slow when working with big datas. However maybe using json path can be slower than loop.
Example for 1 (CREATING OBJECT IN LOOP)
List<objExample > retVal = new List<objExample >();
objExample item;
SqlConnection con = new SqlConnection("CONNECTION STRING");
SqlDataAdapter da;
SqlCommandcmd;
da = new SqlDataAdapter("Select a,b from table", con);
con.Open();
DataTable dt = new DataTable();
da.Fill(dt);
con.Close();
foreach (DataRow itemdr in dt.Rows)
{
item = new objExample();
item.A= itemdr["a"].ToString();
item.B= itemdr["b"].ToString();
item.HasError = false;
retVal.Add(item);
}
return retVal;
Example for 2 (FOR JSON PATH)
List<objExample > retVal;
SqlConnection con = new SqlConnection("CONNECTION STRING");
SqlDataAdapter da;
SqlCommandcmd;
da = new SqlDataAdapter("Select a,b from table for json path", con);
con.Open();
DataTable dt = new DataTable();
da.Fill(dt);
con.Close();
string _json = dt.Rows[0][0].ToString();
retVal = JsonConvert.DeserializeObject<List<objExample>>(_json);
return retVal;
I tried both of them with small data but it didn't satisfy me.
PS : I wrote codes in my mind. Sorry about wrong codes and bad English.
Please guide to me. Thanks.

Just to be clear, are you reading the complete table?
If the goal is to get data that is stored within the json, and maybe perform some queries on it a NoSQL DB seems more appropriate that a SQL one.

Count the number of commands that are dependent on the number of rows. Kind of how we do the Big O Complexity.
I would do something like:
using (var sqlCommand = new SqlCommand("Select a,b from table for json path", con))
{
try
{
using (var reader = sqlCommand.ExecuteReader())
{
while (reader.Read())
{
item = new objExample();
item.A= reader["a"].ToString();
item.B= reader["b"].ToString();
item.HasError = false;
retVal.Add(item);
}
}
}
}
Keep in mind that the sql connection will remain open while you are doing this so its judgement call if you want to do this after loop or in the loop.
And the da.Fill or using the above is same internally, still going to iterate over all rows.
As far as using json is concerned, I wouldn't do that unless you are asking if storing as Json file is a better option than in sql. That's a whole diff question.
You can use PLINQ to process the data in parallel once you have it in the list, even for your above deserialization you can try PLINQ.

Related

How to get datarow cell value with column name datatable

Let Me first tell you what i am doing right now and what problem i am facing.
Right now i am using SqlDataReader for fetching data from database my function looks like
public List<TOPIC_REPORT> gettopicreports()
{
query = "SELECT * FROM [Topic Reports]";
List<TOPIC_REPORT> rpl = new List<TOPIC_REPORT>();
try
{
con.Open();
com = new SqlCommand(query, con);
sdr = com.ExecuteReader();
while (sdr.Read())
{
rt = new TOPIC_REPORT();
rt.ContentId = sdr.GetString(0);
rt.TimesReported = sdr.GetInt64(1);
rt.IsBanned = sdr.GetInt32(2);
rpl.Add(rt);
}
con.Close();
return rpl;
}
catch (Exception e)
{
con.Close();
throw e;
}
}
Problems with above code
Need to assign values to class variables on by one and problematic with multiple select query.
Need to take care of ResultSet , while loop etc.
Above Problem solution use SqlDataAdapter.
public DataSet getdata()
{
com.CommandText = "GetMasterPageData";
com.Connection = con;
com.CommandType = CommandType.StoredProcedure;
con.Open();
SqlDataAdapter adapter = new SqlDataAdapter(com);
DataSet ds = new DataSet();
adapter.Fill(ds);
con.Close();
return ds;
}
This solves above stated problems but
Decrease my prog readability because my front end person don't know in which order i am sending DataTables in DataSet.
Don't know order of selected values in DataTable.
Front end person need to work on column index which is at end will be problematic.
Suggest me what should i do to solve above stated problems.
You can change your query to return multiple result sets, by combining all your queries. For example:
query = "SELECT * FROM [Topic Reports]; SELECT * FROM [Other table]";
After iterating the first result set with SqlDataReader.Read, use SqlDataReader.NextResultSet() method to get to the second result, then use SqlDataReader.Read to iterate the second set.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.nextresult(v=vs.110).aspx
As a side note, if you do this, then you will have to figure out a way of returning collections of two types of objects from your method. It would probably be better to just use 1 method to get a collection of object A, and a different method to get a collection of object B.

Connecting to a Server

Trying to improve my C# to SQL skills... Currently I am using this bit of code to pull data from our application server. I have two different DBA's telling me two other ways to write this, just trying to figure out if this should be improved on or changed. If so, I would really appreciate some kind of examples.
FYI: This code...
db.con(user.Authority)
...Is essentially a 'new sqlconnection' code.
DataTable dtInfo = new DataTable("SomeInfo");
using (SqlConnection con = db.con(user.Authority))
{
string command = "SOME SQL STATEMENT;";
using (SqlCommand cmd = new SqlCommand(command,con))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Param", sqlDbType).Value = Param;
con.Open();
cmd.ExecuteNonQuery();
**********
*** OR ***
**********
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Param", sqlDbType).Value = Param;
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dtInfo );
}
}
}
So, if I'm understanding the provided information, this is my best route?
using (SqlConnection con = db.con(user.Authority))
{
string command = "SELECT [TBL_EMPLOYEE].[ACTIVE_DIRECTORY] FROM [TBL_EMPLOYEE];";
using (SqlCommand cmd = new SqlCommand(command, con))
{
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
MessageBox.Show(reader["ACTIVE_DIRECTORY"].ToString());
}
}
}
And one last thing... This should prevent the need for
cmd.Dispose();
etc...
The code would depend on the specific query. If the query retrieves rows of data (as a SELECT does), then you would go the da.Fill() route. If it's a query that just makes a change to the database (such as INSERT, UPDATE, or DELETE), then you would use ExecuteNonQuery().
I would not use the SqlDataAdapter version. The version that uses the SqlCommand object and the SqlDataReader will perform better, and allows more insight into the actual data being returned.
// Assumes the following sql:
// SELECT foo, bar FROM baz
// error checking left out for simplicity
var list = new List<SomeClass>();
using(var reader = cmd.ExecuteReader()) {
while(reader.Read()) {
list.Add(new SomeClass {
// NOTE: you can see the columns that the c# is referencing
// and compare them to the sql statement being executed
Foo = (string)reader["foo"],
Bar = (string)reader["bar"]
});
}
}
Later as your level of experiance increases you will be able to use other features of the SqlCommand and SqlDataReader classes in order to ensure that the code executes as quickly as possible. If you start using the SqlDataAdapter route, you will eventually have to relearn how to do the exact same things you have already been doing because the SqlCommand and SqlDataReader have operations that do not exist elsewhere in .NET.
ExecuteNonQuery returns the number of rows effected.
A DataTable is not an efficient way to retrieve that number.
int rowsRet = cmd.ExecuteNonQuery();
SqlCommand.ExecuteNonQuery Method

Copying sorted values from one datatable to another Efficiency?

I am using the following code :
EmpInfoDS = new DataSet();
con.Open(); // My connection name
string sqlRecords = "Select * FROM tbl_EmpInfo";
EmpInfoDA = new OleDbDataAdapter(sqlRecords, con);
EmpInfoDA.Fill(EmpInfoDS, "EmpInfo");
var sortedRows = (from myRow in EmpInfoDS.Tables["EmpInfo"].AsEnumerable()
orderby myRow["EmpID"] ascending
select myRow).ToArray();
EmpInfoDS.Tables.Remove("EmpInfo");
DataTable EmpInfo = sortedRows.CopyToDataTable();
EmpInfo.TableName = "EmpInfo";
EmpInfoDS.Tables.Add(EmpInfo);
con.Close();
to sort the values in a datatable. Then removing that datatable and filling the sorted rows into a datatable with the same name.
Can anyone tell me how much efficient this process is. ie. Performance drawbacks ???
If there's a better way to accomplish this; Please tell me.
Any help will be much appreciated. :)
Why don't you just order by in the database? That will always be way more efficient.
i.e.
EmpInfoDS = new DataSet();
con.Open(); // My connection name
string sqlRecords = "Select * FROM tbl_EmpInfo ORDER BY EmpID";
EmpInfoDA = new OleDbDataAdapter(sqlRecords, con);
EmpInfoDA.Fill(EmpInfoDS, "EmpInfo");
con.Close();
Always let the database do work that it's made to do. Sorting is a database function and not a C# function (when it comes to fetching data)
You can try
EmpInfoDS.Tables["EmpInfo"].Sort = "EmpID ASC";
DataTable EmpInfo = EmpInfoDS.Tables["EmpInfo"].DefaultView.ToTable();
EmpInfoDS.Tables.Add(EmpInfo);
//To remove sorting --- EmpInfoDS.Tables["EmpInfo"].Sort = string.Empty;
with this approach you may leave your old DataTable and change sorting expression

c# loop within a loop

I'm currently using DataSets to bring back results in a C# service which I now need to change to loop through the initial set of data and bring back a subset of data from this result.
So I need to loop through these results using an identifier and then show another set of results within a nest below each of these. Using datasets seems no way of making this happen from my limited C# knowledge.
EG> Loop through DB, for each result in DB loop through another table.
[WebMethod(BufferResponse=true,Description="Viewing Things")]
public DataSet MyFunctionIs (int IDtoQuery)
{
MySqlConnection dbConnection = new MySqlConnection("server=na;uid=na;pwd=na;database=na;");
MySqlDataAdapter objCommand = new MySqlDataAdapter("SELECT STATEMENT HERE;", dbConnection);
DataSet DS = new DataSet();
objCommand.Fill(DS,"MyFunctionIs");
}
But even using joins isnt going to fulfill.. I need to query of each row returned on this and return a child set of data for the XML response
Often you can solve this kind of problem by using a SQL query that joins several tables and returns only one set of rows. This gives you a general idea on how you can try to do it:
string ConnectionString = "server=myserver;uid=sa;pwd=secret;database=mydatabase";
using (var con = new SqlConnection(ConnectionString)) {
string CommandText = "SELECT p.firstname, p.lastname, o.operderdate " +
"FROM persons p LEFT JOIN orders o ON p.person_id = o.person_id";
using (var cmd = new SqlCommand(CommandText, con)) {
con.Open();
using (var reader = cmd.ExecuteReader()) {
while (reader.Read()) {
Console.WriteLine("{0} {1}, {2}", reader["firstname"], reader["lastname"], reader["operderdate"]);
}
}
}
}

C# Conversion from VB6 - Recordset

I'm wanting to convert the line to C# from VB6 and am having quite the difficulty doing so.
VB6 Code:
txtFields(4).Text = rsGroup.Fields(0).Value + 1
C#: (what I have so far)
txtFields4.Text = (rsGroup.Fields[0].Value) +1);
What is the correct way to do this?
#jdurman,
An example of retrieving data using a DataSet is:
public DataSet GetDate(string SqlString)
{
SqlConnection sqlConn = new SqlConnection("CONNECTION STRING GOES HERE");
DataSet ds = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(SqlString, sqlConn);
adapter.Fill(ds);
return ds;
}
public void LoopThroughDataExample(DataSet ds)
{
foreach(DataTable dt in ds)
{
foreach(DataRow dr in dt)
{
Console.WriteLine(String.Format("Value is: {0}", dr["DBColumnName"])); // Replace DBColumnName with the name of columns in the Database Table that you want to Extract.
}
}
}
I would not use a RecordSet and Use a DataSet instead.
you can use the System.Data.SqlClient namespace to be able to access Databases and then you can bind controls from your DataSet, makes life alot easier, and also i would avoid doing straight copying of code from VB6. There is alot of new thing in the world of C# that you would never of had the option of using in VB6 prior.
txtFields[4].Text = rsGroup.Fields[0].Value + 1;

Categories