C# sort rows of dataTable using interface - c#

Here is my code for how I get data from a database and add it to a DataTable named data,
I have to sort this all table by data of row "Spelionu skaicius" using interface (increasingly), but I have no idea how to realize that, can someone help with that?
i know there is a lotof ways to sort this, but i have to make this using interface.
using (FbConnection fbBD = new FbConnection(csb.ToString()))
{
fbBD.Open();
FbTransaction transact = fbBD.BeginTransaction();
FbCommand sqlReq =
new FbCommand("SELECT vardas,pavarde,sp_skaicius,spelioniu_sk FROM zaidejai WHERE atspetas='Taip'", fbBD, transact);
using (FbDataReader r = sqlReq.ExecuteReader())
{
while (r.Read())
{
DataRow rw = dt.NewRow();
rw["Vardas"] = r.GetString(0);
rw["Pavarde"] = r.GetString(1);
rw["Skaicius"] = r.GetValue(2);
rw["Spelionu skaicius"] = r.GetValue(3);
data.Rows.Add(rw);
}
}
transact.Commit();
fbBD.Close();
}
P.S. sorry for my English

use the datatable DefaultView property:
data.DefaultView.Sort = "Spelionu skaicius";
you can then work with data.DefaultView (a dataview) or if you need a datatable, you can do this:
data = data.DefaultView.ToTable();
<-- EDIT -->
The above is for regular sorting. If you want to use IComparable, you will have to use custom clases in stead of DataTable. Here's an explanation of how.

It's best if you let the database sort the data so instead, I would change your select to this:
SELECT vardas,pavarde,sp_skaicius,spelioniu_sk
FROM zaidejai
WHERE atspetas='Taip'
ORDER BY spelioniu_sk
Note that I used spelioniu_sk because that's the 4th column listed on your select which is then mapped to Spelionu skaicius in your datatable definition
If you still must sort the datatable after you've gotten the data from the database, perhaps in a different order, you can use the DataView propery of the DataTable as so:
data= data.DefaultView.Sort = "`Spelionu skaicius` ASC";
OR
data = data.DefaultView.Sort = "`Spelionu skaicius` DESC";
Depending on the order that you need to sort by.
Note: I am not sure whether the above Sort Expression will work fine. Since you have decided to name your column with a space in the middle, you may need to enclose the 2 words in either backquotes (as I did above) or maybe square brackets (eg [Spelionu skaicius] ASC)

Related

DataTable Select & DataView Sort

Quick Question.
When I use a DataTable.Select("..") without a Sort condition after using a DataView to Sort the DataTable, should the records be returned in Sorted order ?
Using this method I find that in some cases the records aren't being returned in the correct order, it's hit and miss as well - sometimes they are sometimes they aren't.
If I specify a sort condition to the Select then it all works fine, but the performance implications are drastic for large DataTables.
I've tried using the DataView RowFilter to reduce the hitset but every time I change the RowFilter the performance goes south
MyDtable.Load(MyReader); // its am Oracle DataReader
MyView = new DataView(MYDtable);
MyView.Sort = "CODE, TABLE DESC";
DataRow[] MyRecs = MyDtable.Select("TABLE > 'FREDDO' AND CODE > '661991'");
The number of records returned is always correct, it's just the order that may vary (sometimes)
Thanks,
John
John,
Applying a sort order to a DataView does not change the underlying DataTable it represents. So your code snippet using both DataView properties and DataTable.Select() method will not work as you intended.
When sorting and filtering, you must choose which method is best for presenting and maintaining the data. Here are sorting and filtering usages examples for both DataTable and DataView.
Using DataTable
Syntax:
public System.Data.DataRow[] Select (string filterExpression, string sort);
Example:
DataRow[] MyRecs = MyDTable.Select("TABLE > 'FREDDO' AND CODE > '661991'", "CODE, TABLE DESC");
foreach (DataRow rec in MyRecs)
{ . . . . }
Reference: DataTable.Select() Method Reference
Using DataView
Example:
DataView MyView = new DataView(MyDTable);
MyView.Sort = "CODE, TABLE DESC";
MyView.RowFilter = "TABLE > 'FREDDO' AND CODE > '661991'";
Reference: DataView.RowFilter Property Reference
Note the link takes you to Microsoft’s RowFilter property reference page, the included example shows usage information for both RowFilter and Sort properties.
Or
Syntax:
public DataView (System.Data.DataTable table, string RowFilter, string Sort,
System.Data.DataViewRowState RowState);
Example:
DataView MyView = new DataView(
MyDTable,
"TABLE > 'FREDDO' AND CODE > '661991'",
"CODE, TABLE DESC",
DataViewRowState.CurrentRows);
foreach ( DataRowView rec in MyView )
{ . . . . }
Reference: DataView Class Constructor Reference
Both methods will return the data filtered and sorted correctly. The difference is in how the data is being returned. You must choose the method whose return object best suit your needs.

Select a row from a DataTable and Create New Row to Add to DefaultView

I am trying to select a few rows from a datatable and check for certain conditions. Then I want to create a new row to convert the datatypes of two columns from a string which represents universal time to a string which represents local time and a string to an integer. Here is my code:
dt = (from row in MV.Data.AsEnumerable()
where !(row["conditionCodes"].ToString().Contains("%OC%"))
orderby Convert.ToDouble(row["size"]) descending
select new DataRow
{
size = Convert.ToInt64(row["size"]),
time = Convert.ToDateTime(row["time"]).ToLocalTime
}).CopyToDataTable();
This code doesn't work and doesn't like that I'm trying to create a new DataRow. Help?
The way you want to create a new DataRow, select new DataRow { size = ..., time = ...} does not work.
It seems you try to mix using a constructor and anonymous types, or espacially you are trying to use an object initializer on a DataRow.
Two things won't work out in this code:
Data row only has the following constructor, DataRow(DataRowBuilder builder), which requires a DataRowBuilder. Normally you create DataRows by calling DataTable.NewRow()
Even if you could create a DataRow as you try it, the members size and time would not be known.
I suggest you to use one of the approaches in this question by creating an anonymous type in your select clause and then converting the resulting IEnumerable to a DataTable, either by using refelection or using another approach.
var result = (from row in MV.Data.AsEnumerable()
where !(row["conditionCodes"].ToString().Contains("%OC%"))
orderby Convert.ToDouble(row["size"]) descending
select new
{
size = Convert.ToInt64(row["size"]),
time = Convert.ToDateTime(row["time"]).ToLocalTime
}
// Convert result to datatable using reflection, etc.
// ...

LINQ query not returning rows in string comparison

I'm new to writing LINQ queries, and I'm having trouble with string comparisons. I'm loading the data into a DataTable (confirmed that table in SQL DB and DataTable have same number of rows), but for some reason I can't find a value that I know exists in both.
The text box contains 'servername' while the datarows contain 'servername.mydomain.net', so here's what my code looks like
string strParameter = txtAutoComplete.ToString().ToLower();
//WUG TableAdapter and DataTable
dsCIInfoTableAdapters.DeviceTableAdapter taWUG;
taWUG = new dsCIInfoTableAdapters.DeviceTableAdapter();
dsCIInfo.DeviceDataTable dtWUG = new dsCIInfo.DeviceDataTable();
taWUG.Fill(dtWUG);
var qstWUG = (from row in dtWUG.AsEnumerable()
where row.Field<string>("sDisplayName").ToLower().Contains(strParameter)
select row.Field<string>("sDisplayName"));
Beleive in your LINQ statement dtWUG needs to be dtWUG.AsEnumerable(). Linq only works on data sources that implement the IEnumerable Interface.
You can debug it easier if you add some let statements where you can add breakpoints:
var qstWUG = (from row in dtWUG
let display = row.Field<string>("sDisplayName")
let lower = display.ToLower()
let contains = lower.Contains(strParameter)
where contains
select display).ToArray();
Also convert it to an array using .ToArray() at the end, will make it execute immediately (LINQ is lazy by paradigm, doesn't execute until it's needed), and also easier to look at in subsequent breakpoints.
Yeah, I feel stupid... I forgot to use the textbox.text to assign it to a string
string strParameter = txtAutoComplete.Text.ToLower();
//WUG TableAdapter and DataTable
dsCIInfoTableAdapters.DeviceTableAdapter taWUG;
taWUG = new dsCIInfoTableAdapters.DeviceTableAdapter();
dsCIInfo.DeviceDataTable dtWUG = new dsCIInfo.DeviceDataTable();
taWUG.Fill(dtWUG);
var qstWUG = (from row in dtWUG.AsEnumerable()
let display = row.Field<string>("sDisplayName")
where display.ToLower().Contains(strParameter)
select display).ToArray();

Sort and Search Datatable

I have a datatable that has been bound to a Gridview in code behind. This means i would have to sort columns in code behind and when searching for a record i would imagine that would be done in code behind too.
The code i have to sort the gridview is
Private Function GetCustData As Datatable
Dim dt as new datatable
dt = GetDataFromBusinessLayer(CustomerID)
Return dt
End Function
And the code to sort
Private Sub gv_Sorting(sender As Object, e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles gv.Sorting
If e.SortExpression = "Name"
gv.DataSource = GetCustData '.DefaultView.Sort = "Name" & "DESC"
gv.DataBind()
End If
End Sub
As you can tell i tried using .DefaultView.Sort = "Name" & "DESC" but this didnt work and got the error Data source is an invalid type. It must be either an IListSource, IEnumerable, or IDataSource. Searching around most are using Viewstate but that doesnt seem applicable in my case.
Can anyone advise how i would sort one/multiple columns?
In addition i will like to have a textbox which will search for the Name column. I think the above should suffice when it comes to it but if not could someone put me on the right track so i can work towards that now rather than having to change what im doing at a later stage?
First of all, your current code does not have a space. To sort by Name DESC your Sort string would need to be: "Name DESC".
To set the Sort string to multiple columns, just add a comma between each one, like this:
Dim dt as new datatable = GetCustData(1)
dt.DefaultView.Sort = "Name DESC, FirstName ASC"
gv.DataSource = dt.DefaultView
gv.DataBind()
I think you can create a list of rows
List<DataRow> list = dt.AsEnumerable().ToList();
and then when you have a list you can now use sort
list.OrederBy(c=>c.///specific value in your list)
What about using Linq to do the sort for you.
Dim dt as new datatable
dt = From dr as Datarow in GetDataFromBusinessLayer(CustomerID)
Order by dr.item("First Sort field), dr.Item("Second Sort Field")
Select dr
Return dt
... I did this without the IDE, but that should do the trick, I believe.
Here's one exmaple online - Sorting DataTable with Linq
Hope this helps.

How to get unique records of specific columns of data table

I have a DataTable imported from Excel file.
Data i need is only unique from specific columns of the DataTable.
The unique data i meant is like when a command DISTINCT is used in SQL Select Query.
I want to get the list of the unique data from the DataTable Column and put them into List
I think LinQ can be used for this matter but i'm not so familiar with it.
I was thinking of code like this below
var data is from MyDataTable
where MyDataTable.ColumnName = "SpecificColumn"
select MyDataTable["SpecificColumn"]).UniqueData;
List<string> MyUniqueData = new List<string>();
foreach(object obj in data)
{
if(MyUniqueData.NotContain(obj))
MyUniqueData.add(obj);
}
I hope someone can drop off some knowledge to me.
var unique = data.Distinct().ToList();
What you're looking for is .Distinct(). See MSDN documentation here. You can specify your own comparer if you need something specific and it will return only unique records.
If you have a Datatable or DataView, inorder to get unique records from a column, you have to write this.
this would be simple.
DataTable dtNew = dt.DefaultView.ToTable(true, "ColName"); // for Datatable
DataTable dtnew= dv.ToTable(true, "ColName"); // for DataView

Categories