Copying sorted values from one datatable to another Efficiency? - c#

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

Related

Better way to get json data from relational databases?

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.

C# sqlite copy a datatable to another datatable in faster way

Can anyone share how to coding copy a datatable to another datatable in faster way for C# sqlite? Thanks.
And also need to change column name also. i tried to manually select and update, but encountered error. Appreciate for your sharing. Thanks.
or how can i amend the column header when display datatable in datagridview? Thanks.
dbConnect = new SQLiteConnection("Data Source=school.db;Version=3;");
dbConnect.Open();
cmd4 = new SQLiteCommand();
cmd4 = dbConnect.CreateCommand();
cmd4.CommandText = "DELETE FROM GroupEven";
cmd4.ExecuteNonQuery();
cmd4.CommandText = "SELECT Day, Day_ID, Standard, Timeslot1_TeacherName, Timeslot1_Subject, Timeslot2_TeacherName, Timeslot2_Subject, Timeslot3_TeacherName, Timeslot3_Subject, Timeslot4_TeacherName, Timeslot4_Subject, Timeslot5_TeacherName, Timeslot5_Subject, Timeslot6, Timeslot7_TeacherName, Timeslot7_Subject, Timeslot8_TeacherName, Timeslot8_Subject, Timeslot9_TeacherName, Timeslot9_Subject, Timeslot10_TeacherName, Timeslot10_Subject, Timeslot11_TeacherName, Timeslot11_Subject FROM TimetableFinal";
DataTable dt4 = new DataTable();
SQLiteDataAdapter da4 = new SQLiteDataAdapter(cmd4);
da4.Fill(dt4);
foreach (DataRow dr4 in dt4.Rows)
{
cmd4.CommandText = "INSERT INTO TimetableFinal2 (Day, Day_ID, Standard, 7:30am-8:00am, 7.30am-8.00am, 8:00am-8:30am, 8.00am-8.30am, 8:30am-9:00am, 8.30am-9.00am, 9:00am-9:30am, 9.00am-9.30am, 9:30am-10:00am, 9.30am-10.00am, 10:00am-10:20am, 10:20am-10:50am, 10.20am-10.50am, 10:50am-11:20am, 10.50am-11.20am, 11:20am-11:50am, 11.20am-11.50am, 11:50am-12:20pm, 11.50am-12.20pm, 12:20pm-12:50pm, 12.20pm-12.50pm) VALUES (#Day, #Day_ID, #Standard, #7:30am-8:00am, #7.30am-8.00am, #8:00am-8:30am, #8.00am-8.30am, #8:30am-9:00am, #8.30am-9.00am, #9:00am-9:30am, #9.00am-9.30am, #9:30am-10:00am, #9.30am-10.00am, #10:00am-10:20am, #10:20am-10:50am, #10.20am-10.50am, #10:50am-11:20am, #10.50am-11.20am, #11:20am-11:50am, #11.20am-11.50am, #11:50am-12:20pm, #11.50am-12.20pm, #12:20pm-12:50pm, #12.20pm-12.50pm)";
cmd4.Parameters.AddWithValue("#Day", dr4["Day"].ToString());
SQLite does support Joinings Insert statements, something like this.
INSERT INTO 'tablename' ('column1', 'column2')
VALUES
('data1', 'data2'),
('data3', 'data4'),
('data5', 'data6'),
('data7', 'data8');
See this.. http://www.sqlite.org/lang_insert.html
and then execute this in one go. Also, Make sure you do this in transactions and wrap around in using statements
using(var dbConnect = new SQLiteConnection("DataSource=school.db;Version=3;"))
{
dbConnect.Open();
using(var transaction = dbConnect.BeginTransaction())
{
string insertQuery = ...// your insert query
using (var cmd = dbConnect.CreateCommand())
{
cmd.CommandText = insertQuery;
foreach (DataRow dr4 in dt4.Rows)
{
cmd.Parameters.AddWithValue(...);
}
cmd.ExecuteNonQuery()
}
transaction.Commit();
}
}
Regarding your second part: How can i amend the column header when display datatable in datagridview,
thats totally separate, has nothing to do with Sqlite insertions.
After getting the data source you can do something like this
dataGridView1.Columns[i].HeaderText = "My New header";

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.

Asp.Net Application Properly using .RowFilter to Textbox

In the application im writing im connecting to a SQL database, then using an Adapter to hold the returned results but now I want to filter the results with .RowFilter three times return the filtered result each time to Textbox. I'm not sure if this is best executed with an if statement or with some Switch statement. Heres the code for a better idea of what im trying to do.
using (con)
{
con.Open();
SqlCommand cmd = new SqlCommand(selectSQL, con);
cmd.Parameters.AddWithValue("#num", IDnumber);
//SQLConnection Established and Opened
SqlDataAdapter adapter = new SqlDataAdapter(selectSQL, con);
DataTable dt = new DataTable();
adapter.Fill(dt);
//Adapter Created and Filled
DataView dvQ = dt.DefaultView;
dvQ.RowFilter = "AccountType = Q";
QualVol.Text = "TotalVolume".ToString();
//First Filter then Change QualVol textbox text to Column data TotalVolume
dvQ.RowFilter = "AccountType = N";
NonVol.Text = "TotalVolume".ToString();
//Filter original DataView then Change NonVol textbox text to Column data TotalVolume
dvQ.RowFilter = "AccountType = M";
MidVol.Text = "TotalVolume".ToString();
//Filter original DataView then Change NonVol textbox text to Column data TotalVolume
}
As per dotnetperls performance of a switch is better than an if but also gives a good clue on what situation an if performs better than the switch
http://www.dotnetperls.com/if-switch-performance

Question on updating/inserting a datatable in a dataset

I need to open a connection to SQL database and read a subset of a table and either update a record if exists or insert if not found. Having truoble updating
SqlConnection conn = new SqlConnection(ConnectionStrings.PgenIntranet.SqlClientConnectionString);
SqlDataAdapter indicators = new SqlDataAdapter();
string sql = "SELECT * FROM BusinessApplications.tbl_WPI_Site_Indicators where Year = '" + year +
"' and Month = '" + month + "' and PlantId = " + site.ID;
indicators.SelectCommand = new SqlCommand(sql, conn);
SqlCommandBuilder cb = new SqlCommandBuilder(indicators);
indicators.UpdateCommand = cb.GetUpdateCommand();
DataSet ds = new DataSet();
indicators.Fill(ds, "indtable");
DataTable indtable = ds.Tables["indtable"];
// this logic not working
if (indtable.Rows.Count == 0) { indtable.NewRow(); }
DataRow dr = indtable.NewRow();
/// not sure how to make this work
indtable[1]["PlantId"] = site.ID;
dr["PlantId"] = site.ID;
It's been a while since I've used DataSets/DataTables/DataRows, but I think you're close. If I remember correctly, you'll need to create a new row object like you do here:
DataRow dr = indtable.NewRow();
Then populate that row with your data, also similar to how you were doing it:
dr["PlantId"] = site.ID;
Then finally add that row to the rows collection in the DataTable. (You'll want to double-check if your DataTable instance is actually the DataTable in the Tables collection on the DataSet, I don't recall the specifics. It may be safer to reference the Tables collection directly rather than put it in its own object.)
Note that this does not add the row back to the database. It just adds it to the DataTable instance. You'll need to update back to the database accordingly. And this setup that you have here is a bit... messy... so I have no quick answer for that. Since you're just using plain old ADO then I guess you'll need to create an update command and populate it and run it against the connection accordingly.
In doing so, please take care to fix SQL injection vulnerabilities like the one you have there :)
Don't forget to add your new row to the table, then call update...
indtable.Rows.Add(dr);
ds.Update();

Categories