tags:

views:

50

answers:

3

I'm having a rough time figuring out exactly how to do a LINQ query on a DataTable and return a full row while having the WHERE clause test on a sum.

My code:

transactionsToRemove.AddRange(paymentTransactionResults
     .AsEnumerable()
     .Where(...)
     .GroupBy(r => (decimal)r["AccountNumber"]));

There are multiple transactions for each AccountNumber, and I need to sum those together and determine whether they're less than a user inputted amount (For my purpose, it's called balanceGreaterThan). I can't find any examples to go by where someone has done this sort of thing.

Thanks in advance, SO.

Edit: My apologies -- The column I need to sum is called "Balance"

Edit 2: Final code

transactionsToRemove.AddRange(paymentTransactionResults
     .AsEnumerable()
     .GroupBy(r => r.Field<string>("AccountNumber"))
     .Where(g => g.Sum(r => r.Field<decimal>("Balance")) < balanceGreaterThan)
     .SelectMany(g => g));

I had to change the GroupBy to use r.Field rather than r["AccountNumber"]

+3  A: 
transactionsToRemove.AddRange(paymentTransactionResults
     .AsEnumerable()
     .GroupBy(r => (decimal)r["AccountNumber"])
     .Where(g => g.Sum(r => (decimal)r["Balance"]) <= someInput)
     .SelectMany(g => g));
lasseespeholt
Won't compile. `g` isn't an `IEnumerable<decimal>`.
SLaks
Try now - I've included `SelectMany` :)
lasseespeholt
Yeah, I tried it on some wrong input data (not on a DataTable). I think it will work now.
lasseespeholt
+4  A: 

You're trying to filter the groups themselves (to find which groups have a large sum), not the rows that go into the groups.
Therefore, you need to put the Where() call after the GroupBy:

transactionsToRemove.AddRange(paymentTransactionResults
     .AsEnumerable()
     .GroupBy(r => (decimal)r["AccountNumber"])
     .Where(g => g.Sum(r => r.Field<decimal>("Balance") < balanceGreaterThan));

EDIT: If you want to get an IEnumerable<DataRow> back (as opposed to an IEnumerable<IGrouping<DataRow>>), you'll need to add .SelectMany(g => g).

SLaks
Wow, SLaks is trying to be extremely picky with every other answer to get his own upvoted. Sly!
Timwi
@Timwi: I do this to most answers, even if I'm not competing with them. This is a fairly beginner-level question, so it's important to get the details right. Also, I didn't downvote anything.
SLaks
Yeah, I needed IEnumerable<DataRow> back. You've been more than helpful. Full code posted above.
treefrog
OK, out of curiosity, where does your `AsEnumerable()` come from? There is no such method on `System.Data.DataTable`, and nor does it implement any interface that has this as an extension method?
Timwi
AFAIK, you can't perform LINQ queries on non-typed DataTables without the AsEnumerable().
treefrog
@Timwi: It's an extension method on DataTable defined in `System.Data.DataTableExtensions`, in System.Data.DataSetExtensions.dll.
SLaks
Thanks! ———————
Timwi
+1  A: 

I think you want something like:

transactionsToRemove.AddRange(paymentTransactionResults 
     .AsEnumerable() 
     .GroupBy(r => (decimal)r["AccountNumber"])); 
     .Where(grp => grp.Sum(r => r["amount"]) < balanceGreaterThan);
James Curran
You forgot a cast.
SLaks