Lambda Distinct not working - c#

I am unable to get a distinct list of 'Order' from my Lambda query. Even though am using the keyword Distinct() it is still returning repeated select list item.
public ActionResult Index()
{
var query = _dbContext.Orders
.ToList()
.Select(x => new SelectListItem
{
Text = x.OrderID.ToString(),
Value = x.ShipCity
})
.OrderBy(y => y.Value)
.Distinct();
ViewBag.DropDownValues = new SelectList(query, "Text", "Value");
return View();
}
Any suggestions please?
UPDATE
Sorry guys I genuinely missed out the Distinct() from my code. I have now added it to my code.
I am basically trying to get all distinct rows where yes the values are same but the ids are different.
Same as this SQL Query......
SELECT distinct [ShipCity] FROM [northwind].[dbo].[Orders] ORDER by ShipCity

I'm assuming you removed your distinct from the end of the query.
Actually for that matter i don't see how you could get duplicate orders at all since you're doing nothing in your query except selecting and your query is on a table in a database, so you already can't get the same row multiple time.
What do you call a "duplicate"? If you mean two rows with the same values except their ID that's not a duplicate at all, that's just two unrelated rows, with the same values . . .
If on the other hand you mean you expect them to be equal because you're tossing the .Distinct after the select and you're only using OrderId and ShipCity in there for which there are duplicates (and i really don't see why a column named OrderId in an orders table should have duplicates but that's another issue) then that still won't work because you're NOT selecting OrderId nor ShipCity, you're selecting a new SelectListItem and if you create two reference types with the same value, they're not equal in .NET, they need to be the same instance to be equal, not two instances with different values.
edited following your comment :
var query = _dbContext.Orders
.ToList()
// Group them by what you want to "distint" on
.GroupBy(item=>item.ShipCity)
// For each of those groups grab the first item, we just faked a distinct)
.Select(item=>item.First())
.Select(x => new SelectListItem
{
Text = x.OrderID.ToString(),
Value = x.ShipCity
})
.OrderBy(y => y.Value)
.Distinct();

Related

Getting null data when executing LINQ to Entities query

I have the following Book table:
From this table, I am trying to get the latest registrationNumber based on the group ID as an input from the user.
So, my query looks like this at the moment:
var booksQuery = _context.Books.Where(g => g.GroupId == id)
.OrderByDescending(g => g.RegistrationNumber).GroupBy(g => g.GroupId);
id is the group Id specified by the user. So for example, if id = 15, then I should get the 15:6 as my latest registration number. To do that, I basically grouped by id and ordered the result by descending order. But that is giving me null results. Anyone know why? I am very new to this LINQ-Entitiy coding.
As mentioned by others you really should make your registrationNumber field an integer since you are wanting to sort on it. In the event, you can't make the change, below is a Linq query that basically parses the registration number and converts to an integer to sort on the first and second part by splitting at the colon. This works for sorting when you have 15:10, etc, as in the string sort 15:6 comes before 15:10
var booksQuery = books.Where(g => g.GroupId == id).ToList();
var bookWanted = booksQuery
.OrderByDescending(g => int.Parse(g.registrationNumber.Split(':')[0]))
.ThenByDescending(g=> int.Parse(g.registrationNumber.Split(':')[1]))
.FirstOrDefault();

Why is linq reversing order in group by

I have a linq query which seems to be reversing one column of several in some rows of an earlier query:
var dataSet = from fb in ds.Feedback_Answers
where fb.Feedback_Questions.Feedback_Questionnaires.QuestionnaireID == criteriaType
&& fb.UpdatedDate >= dateFeedbackFrom && fb.UpdatedDate <= dateFeedbackTo
select new
{
fb.Feedback_Questions.Feedback_Questionnaires.QuestionnaireID,
fb.QuestionID,
fb.Feedback_Questions.Text,
fb.Answer,
fb.UpdatedBy
};
Gets the first dataset and is confirmed working.
This is then grouped like this:
var groupedSet = from row in dataSet
group row by row.UpdatedBy
into grp
select new
{
Survey = grp.Key,
QuestionID = grp.Select(i => i.QuestionID),
Question = grp.Select(q => q.Text),
Answer = grp.Select(a => a.Answer)
};
While grouping, the resulting returnset (of type: string, list int, list string, list int) sometimes, but not always, turns the question order back to front, without inverting answer or questionID, which throws it off.
i.e. if the set is questionID 1,2,3 and question A,B,C it sometimes returns 1,2,3 and C,B,A
Can anyone advise why it may be doing this? Why only on the one column? Thanks!
edit: Got it thanks all! In case it helps anyone in future, here is the solution used:
var groupedSet = from row in dataSet
group row by row.UpdatedBy
into grp
select new
{
Survey = grp.Key,
QuestionID = grp.OrderBy(x=>x.QuestionID).Select(i => i.QuestionID),
Question = grp.OrderBy(x=>x.QuestionID).Select(q => q.Text),
Answer = grp.OrderBy(x=>x.QuestionID).Select(a => a.Answer)
};
Reversal of a grouped order is a coincidence: IQueryable<T>'s GroupBy returns groups in no particular order. Unlike in-memory GroupBy, which specifies the order of its groups, queries performed in RDBMS depend on implementation:
The query behavior that occurs as a result of executing an expression tree that represents calling GroupBy<TSource,TKey,TElement>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, Expression<Func<TSource,TElement>>) depends on the implementation of the type of the source parameter.`
If you would like to have your rows in a specific order, you need to add OrderBy to your query to force it.
How I do it and maintain the relative list order, rather than apply an order to the resulting set?
One approach is to apply grouping to your data after bringing it into memory. Apply ToList() to dataSet at the end to bring data into memory. After that, the order of subsequent GrouBy query will be consistent with dataSet. A drawback is that the grouping is no longer done in RDBMS.

With LINQ DISTINCT a Data Table Multiple Columns Excluding a Single Column

I have a C# DataTable. I am retrieving Data into DataTable. After that I am trying to DISTINCT entry's at the same time creating a List<MyObject>.
Here is the code with what I am chasing with:
viewModelList = (from item in response.AsEnumerable()
select new
{
description = DataTableOperationHelper.GetStringValue(item, "description"),
unitCost = DataTableOperationHelper.GetDecimalValue(item, "unitcost"),
defaultChargeable = DataTableOperationHelper.GetBoolValue(item, "defaultChargeable"),
contractId = DataTableOperationHelper.GetIntValue(item, "contractID"),
consumableid = DataTableOperationHelper.GetIntValue(item, "consumableid")
})
.Distinct()
.Select(x => new ConsumablesViewModel(
x.description,
x.unitCost,
x.defaultChargeable,
x.contractId,
x.consumableid)
)
.ToList();
I just want to exclude a single column (consumableid) when I am doing DISTINCT. How could I DISTINCT with my rest of the Data Excluding a single value (consumableid)?
Take a look at this answered question (LinQ distinct with custom comparer leaves duplicates).
Basically, you create an equality comparer for your type that allows you to decide what makes an object distinct.

Getting records in between two records using Linq

I have a list of objects and need to get the list of records from this list. like I have of Countries and I need to get the list of countries which are in between country with name "Australia" and country "Indonasia", the list will not be sorted.
Am using c#.
I tried to use something like, get the index of first and second and then use that to get the list with a for loop, but would be handy if it can be done in single query.
If you do the following:
var elementsBetween = allElements
.SkipWhile(c => c.Name != "Australia")
.Skip(1) // otherwise we'd get Australia too
.TakeWhile(c => c.Name != "Indonasia");
you'll get the result you want without iterating through the list 3 times.
(This is assuming your countries are e.g. Country items with a Name string property.)
Note that this doesn't sort the countries at all - it's unclear from your question whether you want this or not but it's trivial to add an OrderBy before the SkipWhile.
this should do the job
var query = data.SkipWhile(x => x != "Australia").TakeWhile(x => x != "Indonesia")

How to Group and Order in a LINQ Query

I would like to group & order by in a query builder expression. The following query gets me close to what i want but the order by does not appear to be working.
what i have is an object that has unique ids but some will have a common versionId. I would like to get the last edited item of the same versionId. So only one item per version id and i want it to be the last edited one.
IQueryable<Item> result = DataContext.Items.Where(x => (x.ItemName.Contains(searchKeyword) ||
x.ItemDescription.Contains(searchKeyword))
.GroupBy(y => y.VersionId)
.Select(z => z.OrderByDescending(item => item.LastModifiedDateTime).FirstOrDefault());
Edit: I don't really care about the order of the result set, i really just care about what item within the grouping is returned. I want to make sure that the last edited Item within a versionId group is return.
Your z parameter contains the individual group objects.
By calling OrderBy inside of Select, you're ordering the items in each group, but not the groups themselves.
You need to also call OrderBy after Select, like this:
.Select(z.OrderByDescending(item => item.LastModifiedDateTime).FirstOrDefault())
.Where(item => item != null)
.OrderByDescending(item => item.LastModifiedTime)

Categories

Resources