Converting an IEnumerable list to a grouped list in Linq - c#

I have a function that returns the following type:
IEnumerable<IGrouping<String, ExportTransaction>>
In this function I create a list of the following type, using a linq expression:
IEnumerable<ExportTransaction>
The Linq code looks like this:
IEnumerable<ExportTransaction> transactions = ctx.ExportTransactions
.Where(x => x.Id != null);
How can I convert “transactions” to a grouped list of the type shown at the top of this page. The function does various things with the “transactions” so It must stay as “IEnumerable” inside the function but must be converted to the grouped list when returned.

I'll assume that the Transactions have a name property and that's what you want to group the Transactions by. If that's not the case, all you have to do is change the property in the GroupBy call:
var transactions = ctx.ExportTranactions
.Where(x => x.Id != null)
.GroupBy(x => x.Name);

Does it really need to be grouped and if so what do you want to group it by? It sounds to me like you have your data set and you could be trying to force it into a format you don't necessarily need.
Typically to group a data set you'd do something like:
var grouping = ctx.ExportTransactions.Where(x => x.Id != null)
.GroupBy(x => x.Description);
That would create an IEnumerable<IGrouping<string, ExportTransaction>> grouping all the transactions with an identical description, presuming that each transaction had description.
If you need all the records in a single group you can always do the following:
var grouping = ctx.ExportTransactions.Where(x => x.Id != null)
.GroupBy(x => string.Empty);
Which will give you what you need with the group key being an empty string, but I'd strongly advise against it and instead suggest looking at why you need to return a grouping when you don't seem to want to group by anything.

Related

Retrieve the item from the list

I am trying to get the list of Courses from the courseData list item.
However, the following returns me boolean.
var course = courseData.Courses.Select(x => x.Entities.Select(a => a.courseId == courseDto.Id)).FirstOrDefault();
Currently, course is of type IEnumerable<bool> because in your inner Select clause you're projecting from some type a and returning a.courseId == courseDto.Id (bool) which results in an IEnumerable<bool> after the provided lambda is executed for each element of x.Entities.
Once the execution of the outer Select clause is performed this then results in having a type IEnumerable<IEnumerable<bool>> which when you then call FirstOrDefault() upon; simply results in retrieving the first IEnumerable<bool> element.
Now, you're most likely looking for the Where clause so that you can retain all the elements that pass the predicate a => a.courseId == courseDto.Id. We will then flatten the IEnumerable<IEnumerable<Entity>> into IEnumerable<Entity> and then collect to a list or retrieve the first element if exists else the default for reference types (null).
To retrieve a list of courses.
var course =
courseData.Courses
.SelectMany(x => x.Entities.Where(a => a.courseId == courseDto.Id))
.ToList();
To retrieve the first item from the list of courses.
var course =
courseData.Courses
.SelectMany(x => x.Entities.Where(a => a.courseId == courseDto.Id))
.FirstOrDefault();
var Result = Course_Object.Where(u => u.Id == 1).FirstOrDefault();

Casting Nhibernate result into IDictionary<string,int>

I am trying to convert the result of the query into IDictionary
Here string will contain orderId and the int will contain the TradedQuantity
The query below should join three objects Order, OrderRevision and OrderEvent.
1 Order can have many orderRevisions
1 OrderRevision can have many orderEvents
What the query is trying to do is to inner join three objects and get all order objects whose order id matches the list of orderids supplied to it. Then it does a group by based on orderId and gets the latest TradedQuantity from orderEvents object. LatestTradedQuantity will be the TradedQuantityFrom latest OrderEvent. For now the latest orderevent can be regarded as the one that has highest OrderEventId value.
OrderRevision revisionAlias = null;
Order orderAlias = null;
var query =
Session.QueryOver<OrderEvent>()
.JoinAlias(oe => oe.OrderRevision,() => revisionAlias)
.JoinAlias(oe => oe.OrderRevision.Order,() => orderAlias)
.Where(x => x.OrderRevision.Order.SourceSystem.Name.ToLower() == sourceSystem.ToLower())
.WhereRestrictionOn(x => x.OrderRevision.Order.Id).IsIn(orderIds.ToList())
.SelectList(list => list.SelectGroup(x => x.OrderRevision.Order.SourceOrderIdentifier)
.SelectMax(x => x.Id).Select(x => x.TradedQuantity))
.Select(x => new KeyValuePair<string, int?>(x.OrderRevision.Order.SourceOrderIdentifier, x.TradedQuantity)
);
As this query does not do what is supposed to. Could you please help and let me know how the result can be cast into IDictionary?
You have tagged your question with linq-to-nhibernate, so I guess using it instead of queryover would suit you. With Linq, use a sub-query for selecting the "max" order events ids for each order, then query them and project them to a dictionary.
using System.Linq;
using NHibernate.Linq;
...
var orderEventsIdsQuery = Session.Query<OrderEvent>()
.Where(oe => orderIds.Contains(oe.OrderRevision.Order.Id))
.GroupBy(oe => oe.OrderRevision.Order.SourceOrderIdentifier,
(soi, oes) => oes.Max(oe => oe.Id));
var result = Session.Query<OrderEvent>()
.Where(oe => orderEventsIdsQuery.Contains(oe.Id))
.ToDictionary(oe => oe.OrderRevision.Order.SourceOrderIdentifier,
oe => oe.TradedQuantity);
This should do the job. I do not use QueryOver and I will not try to give an answer for doing it with QueryOver.

Issue with many-to-many query with linq to entities

I've got a table
Application
ApplicationID,
NAme
ApplicationSteps
AplicationStepID,
AplicationID,
StepID
ApplicationStepCriterias
ApplicationStepID,
CriteriaID
So I've got one SelectedCriteriaID - a user choose from a dropdown one criteria and he wants all the applications which has this SelectedCriteriaID in the table ApplicationStepCriterias
I tried
var ds = context.Applications
.Where(a => a.ApplicationSteps
.Select(x=>x.ApplicationStepCriterias
.Select(t=>t.CriteriaId))
.Contains(SelectesdCriteria));
But as I have as result IEnumerable<IEnumerable<int>> I cannot use Contains
Just I get a list of all the CriteriaIds for each ApplicationStep(also a sequence). Just I cannot think of way to get in one list all the CriteriIds.
First, let me try to get the names right. This is not a pure many-to-many association, because the junction class is part of the class model. It is what I unofficially call a 1-n-1 association. So you have
Application -< ApplicationSteps >- ApplicationStepCriterias
I'd strongly recommend to use singular names for your classes ...
Application -< ApplicationStep >- ApplicationStepCriterion
... so you can use plural for collection property names without getting confused.
If I'm right so far, you query should be
context.Applications
.Where(a => a.ApplicationSteps
.Any(x => selectedCriteria
.Contains(x.ApplicationStepCriterion.CriteriaId));
(and I'd also prefer CriterionId, probably referring to a Criterion class)
You may try something like this:
var applicationStepIds = context.ApplicationStepCriterias
.Where(i => i.CriteriaID == selectedCriteria)
.Select(i => i.ApplicationStepID)
.Distinct();
var applicationIds = context.ApplicationSteps
.Where(i => applicationStepIds.Contains(i.AplicationStepID))
.Select(i => i.AplicationID)
.Distinct();
var result = context.Applications.Where(i => applicationIds.Contains(i.ApplicationId));

Remove duplicates of a List, selecting by a property value in C#?

I have a list of objects that I need some duplicates removed from. We consider them duplicates if they have the same Id and prefer the one whose booleanValue is false. Here's what I have so far:
objects.GroupBy(x => x.Id).Select(x => x.Where(y => !y.booleanValue));
I've determined that GroupBy is doing no such grouping, so I don't see if any of the other functions are working. Any ideas on this? Thanks in advance.
You can do this:
var results =
from x in objects
group x by x.Id into g
select g.OrderBy(y => y.booleanValue).First();
For every Id it finds in objects, it will select the first element where booleanValue == false, or the the first one (if none of them have booleanValue == false).
If you prefer fluent syntax:
var results = objects.GroupBy(x => x.Id)
.Select(g => g.OrderBy(y => y.booleanValue).First());
Something like this should work:
var result =
objects.GroupBy(x => x.Id).Select(g =>
g.FirstOrDefault(y => !y.booleanValue) ?? g.First())
This assumes that your objects are of a reference type.
Another possibility might be to use Distinct() with a custom IEqualityComparer<>.
This partially answers the question above, but I justed need a really basic solution:
objects.GroupBy(x => x.Id)
.Select(x => x.First())
.ToArray();
The key to getting the original object from the GroupBy() is the Select() getting the First() and the ToArray() gets you an array of your objects, not a Linq object.

Filter to values in collection in one query

I have the following LINQ query:
List<string> Types = (List<string>)Directory.GetFiles(#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727")
.Where(x => System.IO.Path.GetFileNameWithoutExtension(x).Contains("Microsoft"))
.ToList<string>();
How could I modify this so it can only get the values stored in a collection, without writing another LINQ query (which I assume will impact performance?)?
Thanks
Try this:
List<String> Types
= Directory.GetFiles(#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727")
.Where(x => System.IO.Path.GetFileNameWithoutExtension(x).Contains("Microsoft"))
.Where(x => yourCollection.Contains(x))
.ToList();

Categories

Resources