I'm using a linq statement to get my company reviews, but it's skipping the wrong results.
If i pass it currentPage = 1 it gets the right results, if i pass it currentPage 2 it does it wrong. The amount of reviews per page is 10. The GUID id is also passed on correctly.
public IList<SupplierReview> GetAmount(int pageAmount, int currentPage, Guid companyId)
{
var total = _context.SupplierReview.Count();
var skipAmount = pageAmount * (currentPage - 1);
if (skipAmount < total)
{
if (pageAmount < (total - skipAmount))
{
//return the page amount of reviews
return _context.SupplierReview
.Where(x => x.Company.Id == companyId)
.OrderBy(x => x.Id)
.OrderBy(x => x.ReviewDate)
.Skip(skipAmount)
.Take(pageAmount)
.ToList();
}
else
{
//if the left amount is less than the pageAmount,
//then only the leftovers should get taken
return _context.SupplierReview
.Where(x => x.Company.Id == companyId)
.OrderBy(x => x.Id)
.OrderBy(x => x.ReviewDate)
.Skip(skipAmount)
.Take(total - skipAmount)
.ToList();
}
}
//if nothings left, return null
return null;
}
The mistake is probably silly, but I can't seem to see it... Any ideas?
Thanks!
My first thought about skipping too many pages was incorrect. It looks like you are mixing up the total count:
var total = _context.SupplierReview.Count();
then the count which match your company.ID:
Where(x => x.Company.Id == companyId)
I feel like the total calculation should include this Where? Look at your else condition. If you .Take(total - skipAmount), and total was calculated without regard to your company ID, you will end up trying to take too many, potentially a non-existent amount.
It is fine to specify bigger number than (actual)collection count to both Skip & Take extension methods, in this case you get an empty collection.
That means we can refine the code as shown below.
return _context.SupplierReview
.Where(x => x.Company.Id == companyId)
.OrderBy(x => x.Id)
.OrderBy(x => x.ReviewDate)
.Skip(pageAmount * currentPage) //use currentPage + 1 if index assumed to start with 1
.Take(pageAmount)
.ToList();
Related
I'm using session.Query for getting data from RavenDB
I want to get documents where price field greater or equal to price parameter.
I try-
session.Query<Index.Result, Index>()
.Where(x => x.Id == Id
&& x.Price >= Settings.Price)
.TransformWith<Transformer, Transformer.Result>()
.ToList();
But I get wrong results - only 2 documents instead of 3.
If I add the predicate after the query I get the right result =3 documents
var a = session.Query<Index.Result, Index>()
.Where(x => x.Id == Id)
.TransformWith<Transformer, Transformer.Result>()
.ToList();
var b = a.Where(x => x.Price >= Settings.Price)
.ToList();
Why the session.Query doesn't work correctly?
In Lucene Syntax I get the correct results - 3 documents.
session.Advanced.DocumentQuery<Index.Result, Index>()
.Where(string.Format("Id :{0} Price : [{1} TO *]" , Id, Price))
.SetResultTransformer("Transformer")
.SelectFields<Transformer.Result>()
.ToList();
But I want to use the session.Query syntax.
So how can I use the session.Query syntax linq syntax to get the result according to the greeter or equal predicate?
Thank in advance
I am using the query below to grab all records that have a SubCategoryName == subCatName and i want to return all of there ProductID's as a list of ints. Problem is when my code runs it is only returning 1 int(record) instead of all. How can i make it return all of the records that have that subCatName? Its returning a count = 1 with a capacity of 4. So it is a int[4] but only the first [0] is = to a actual product ID the rest returning zero?
public List<int> GetPRodSubCats(string subCatName)
{
var _db = new ProductContext();
if (subCatName != null)
{
var query = _db.ProductSubCat
.Where(x => x.SubCategory.SubCategoryName == subCatName)
.Select(p => p.ProductID);
return query.ToList<int>();
}
return null;
}
As Daniel already has mentioned, the code should work. But maybe you are expecting that it's case-insensitive or ignores white-spaces. So this is more tolerant:
subCatName = subCatName.Trim();
List<int> productIDs = _db.ProductSubCat
.Where(x => String.Equals(x.SubCategory.SubCategoryName.Trim(), subCatName, StringComparison.OrdinalIgnoreCase))
.Select(p => p.ProductID)
.ToList();
This seems more like an expected behavior here. How do you know you don't only have 1 record that satisfies the Where predicate.
Your code is correct, however you might want to normalize your comparison.
x => x.SubCategory.SubCategoryName == subCatName
to use a specific case for instance:
x => x.SubCategory.SubCategoryName.ToLower() == subCatName.ToLower()
you might also consider a Trim.
I'm trying to find a way to group records by date (not taking into account time) using the LINQ method syntax but only select one instance of each record (which is ItemId within the model)
My simple query is as follows:
range1.Count(x => ((x.OpenedDate >= todayFirst) && (x.OpenedDate <= todayLast))
How could I count the unique records within this range by ItemId?
Sounds like you want:
var query = range1.Where(x.OpenedDate >= todayFirst && x.OpenedDate <= todayLast)
.GroupBy(x => x.ItemId)
.Select(g => new { ItemId = g.Key, Count = g.Count() });
foreach (var result in query)
{
Console.WriteLine("{0} - {1}", result.ItemId, result.Count);
}
It's possible that I haven't really understood you properly though - it's not clear whether you really want to group by date or item ID
EDIT: If you just want the count of distinct item IDs in that range, you can use:
var count = range1.Where(x.OpenedDate >= todayFirst && x.OpenedDate <= todayLast)
.Select(x => x.ItemId)
.Distinct()
.Count();
Given following structure: a person has functions. Each function has roles. Each roles has features. Now I would like to figure out with linq if a given person has a certain feature, but I am doing something wrong with this query. As a result I always get the count of the functions (but I'd like to get the count of the features):
var count = person.Functions
.Select(fu => fu.Roles
.Select(r => r.Features
.Where(f => f.FeatureId == 99999)))
.Count();
What am I doing wrong here? According to this query I expect either 0 (hasn't got the feature) or 1.
var query = from function in person.Functions
from role in function.Roles
from feature in role.Features
where feature.FeatureId == 99999
select feature;
var count = query.Count();
or
var count = person.Functions
.SelectMany(function => function.Roles)
.SelectMany(role => role.Features)
.Count(feature => feature.FeatureId == 99999);
If you don't need the exact count but just want to know if the person has the feature or not, use Any instead of Count.
var count = person.Functions
.SelectMany(p => p.Roles)
.SelectMany(r => r.Features)
.Where(f => f.FeatureId == 99999)
.Count();
I'm not really sure, but I think you want the total number of Features with teh given Id. You would want to use SelectMany.
This query looks at the record before it and subtracts the times to calculate the total amount of time. However, when the first record is evaluated it throws an error on the third line after the subtraction. Index out of bounds. When I remove the Sum() then the error goes away, but I need the sum efficiently.
var allRecorded = queryable.Where(x => x.DataId== Id);
var dataFiltered = allRecorded.Where(x => x.DataValue >= lowerThreshold && x.DataValue < upperThreshold);
var sumOfExactTimes = dataFiltered.Select(times => (times.EndTime - allRecorded.Where(time2 => time2.EndTime < times.EndTime).Select(x => (DateTime?) x.EndTime).Max()).GetValueOrDefault().TotalMinutes).Sum();
Is there anything else I'm missing?
The problem with the query you have above is that when you reach the item with the minimum EndTime, nothing is found giving you an empty result. You then try to take the maximum of an empty collection which causes the error.
However this query could be simplified tremendously. It would be easier to sort it first then aggregate to find the differences.
var data = queryable
.Where(item => item.DataId == id
&& item.DataValue >= lowerThreshold
&& item.DataValue < upperThreshold)
.OrderBy(item => item.EndTime)
.ToList();
var sumOfExactTimes = data.Skip(1)
.Aggregate(
Tuple.Create(data.First(), 0.0), // [1] Prev Item [2] Result
(seed, item) =>
Tuple.Create(
item,
seed.Item2 + (item.EndTime - seed.Item1.EndTime).TotalMinutes),
result => result.Item2);