views:

43

answers:

2

I have a Typed DataSet DataTable which inherits TypedTableBase<T>, which in turn implements IEnumerable<T>. I can't seem to get this to work.

myDataTable.OrderBy(x => x.ID).ThenBy(y => y.ID2);

Instead I have to assign this statement to an IEnumerable(or List), then refill my DataTable manually with the newly ordered IEnumerable before I commit. Is this how it is intended to be? I've thought about creating my own extension method that will empty/refill my DataTables, but would this be wise?

Note: Typically I only need to sort for viewing purposes using DataView. But in this case I have a custom routine that must create a new access database with sorting requirements, which means I need to sort the actual DataTable so that I may re-commit it.

Thank you.

+2  A: 

Linq extension methods do not alter the source enumerable.

var numbers = new int[]{1,2,3};
var reversed = numbers.OrderByDescending(x=>x);
foreach(var number in reversed)
  Console.Write(number); // 321
foreach(var number in numbers)
  Console.Write(number); // 123

If you want to sort a DataTable, you should be using DataViews. You create a view on your DataTable, then apply a Sort or Filter to it, then bind against it. Keep in mind DataSets are an older technology and not quite up to date on the latest and the greatest. A "newer" approach would be to use the Entity Framework.

Will
+2  A: 

In order to do what you want, you must add the following reference to your project:

System.Data.DataSetExtensions

Once you have that added, you can order your DataTable like this:

var query = myDataTable.OrderBy(x => x.ID).ThenBy(y => y.ID2);

// use the DataView generated from the LINQ query
DataView dtv = query.AsDataView();  

In order to iterate through the DataView, you can do the following:

var dtv = query.AsDataView();
foreach(DataRowView rw in dtv)
{
    // you can also cast back to the typed data...
    MyCustomRowType typedRow = (MyCustomRowType) rw.Row;

    // do something here...
}

Alternatively you can typecast via LINQ this way:

var dtv = query.AsDataView().Cast<MyCustomRowType>();

// rowItem is of type MyCustomRowType...
foreach(var rowItem in dtv)
{
    // do something here...
}
code4life
This is not true. You can not alter the source enumerable, which is what I was asking. You would have to assign this to a new enumerable. Do you think I would know what the TypedTableBase<T> is without knowing to reference DataSetExtensions?
jsmith
Sorry, didn't mean to offend you. I honestly misread your question. All the best!
code4life
@jsmith: I updated my answer. Hopefully I'm making a bit more sense this time...!
code4life
@coded4life ;) You didn't offend me, just got a chuckle out of the answer. I tend to forget that my sarcasm is unheard through the typing of my fingers. Much appreciation friend.
jsmith
@jsmith: no worries then. all the best!
code4life
+1 actually I think this is a better answer than mine. I knew about the DataSet extensions, but I haven't used them much. Also, since at this point you're databinding, it doesn't matter if your view is strongly typed or not. So this is a great answer all around.
Will
@Will at this point I need to do research before accepting any answer. I am unaware on how to bind a DataTable to a DataView so that the physical DataTable resorts with the DataView. As of yesterday I thought it not possible without refilling the table.
jsmith
@jsmith you can't "sort" a DataTable. You can create a sorted view of it, which shows the data in the table in the order you choose. Sorting in this respect is a function of the UI, and if your design requires the physical arrangement of your data match exactly how it is displayed to the user your design probably needs some work.
Will
@Will my user requires it to be delivered in an access database format. It is not an application I am building, but rather a reporting tool to automate thousands of lines of data. I have no control over how they want it reported. Which is why I have to sort the DataTable, not the view. Furthermore, I have to deal with data in a very hacky way given to me by two other developers. The only quick solution is to resort the DataTable. Which it seems the only way to do is to assign the data to a query, empty, than refill. Which is why I am likely to choose your answer.
jsmith
@jsmith my apologies. You could iterate the DataView rather than the DataTable when writing to the access database. If you can't change the way the database is created, then yes, you'll have to dump and refill.
Will
@jsmith I posted some further info on iterating through a DataView... HTH!
code4life