Greater and equal predicate does not work- RavenDB session.Query - c#

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

Related

Field expression GroupBy not returning included objects

In this code:
var dbrepayments = _context.Repayments.Include("Loan").Include("Loan.Borrower").Include("Loan.LoanProduct")
.Where(c => c.PaidOn == null && c.DateOfRepayment <= today)
.GroupBy(c => c.Loan.Id, (key, g) => g.OrderByDescending(c => c.Id).FirstOrDefault())
.OrderBy(c => c.DateOfRepayment);
_context is ApplicationDbContext type that I am using to get results from database using Code-First approach.
The problem is when I try to iterate through dbrepayments and get the value of Loan, Loan.Borrower, and Loan.LoanProduct objects they are showing as null. But when I remove GroupBy, these objects are returned correctly.
I'd wager the issue here is the element selector in your GroupBy statement:
(key, g) => g.OrderByDescending(c => c.Id).FirstOrDefault()
This didn't make a lot of sense when I first read it. You are taking repayments grouped by loan, but then trying to select just the last repayment for each loan? Followed by ordering those first repayments by date.
I believe this will give you the results you're looking for with the eager loaded relationships:
var dbrepayments = _context.Repayments.Include("Loan").Include("Loan.Borrower").Include("Loan.LoanProduct")
.Where(c => c.PaidOn == null && c.DateOfRepayment <= today)
.GroupBy(c => c.Loan.Id)
.Select(c => c.OrderByDescending(x => x.Id).FirstOrDefault())
.OrderBy(c => c.DateOfRepayment);
GroupBy will respect Include but if you are using a select expression, that overrides it. You cannot add Include inside the selector as that is working with IEnumerable of the expected results. Instead, group the results by loan as expected, but then Select from the results to get the latest repayment. This will give you a list of the latest repayments that you can then order.

LINQ - GroupBy Year/Month

I'm trying to populate graph data with total amount(sum) by a last four months, and visually it would look like this:
I've tried so far to group data by year and by a month, but I'm not sure if it's right approach cuz this doesn't work..
Here is the code:
var testQUERY = await _context.Calculation
.AsNoTracking()
.Where(x => (x.PaymentDate != null && x.PaymentDate > DateTime.UtcNow.AddMonths(-4)))
.GroupBy(x => new { x.PaymentDate.Value.Year, x.PaymentDate.Value.Month}).ToListAsync();
Here's my paymentDate :
And I'm wondering how could I group by month only..
Error I'm facing is next:
Error generated for warning
'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning: The
LINQ expression 'GroupBy(new <>f__AnonymousType0`2(Year =
Convert([p].PaymentDate, DateTime).Year, Month =
Convert([p].PaymentDate, DateTime).Month), [p])' could not be
translated and will be evaluated locally.'. This exception can be
suppressed or logged by passing event ID
'RelationalEventId.QueryClientEvaluationWarning' to the
'ConfigureWarnings' method in 'DbContext.OnConfiguring' or
'AddDbContext'.
P.S If I better think because I'm using
x.PaymentDate != null && x.PaymentDate > DateTime.UtcNow.AddMonths(-4)
I don't need new anonymous type where I included year also.. but obliviusly I'm trying to group by column which does not exist.. ?
Try using this one. See comments for possible fixes.
var testQUERY = await _context.Calculation
.AsNoTracking()
.Where(x => x.PaymentDate != null)
.Select(x => new { PaymentDate = x.PaymentDate.Value, Row=x }) // pre-select non-null payment date
.Where(x => x.PaymentDate > DateTime.UtcNow.AddMonths(-4)) // this should go after the grouping, as it might include from just part of the month
.GroupBy(x => new { x.PaymentDate.Year, x.PaymentDate.Month})
.Select(grp=> new { grp.Key.Year, grp.Key.Month, Count = grp.Count()) // flatten group and calculate aggregates
.ToListAsync();

c# LINQ AsEnumerable Groupby Where

I have a datatable that I am returning to the UI layer.
I have multiple tables with the same FirstId value. A few may have a value in teh FieldOne. I only want to group the records where FieldOne is null.
I tried the following LINQ statement with .Where and .Groupby but the .Where removes all the records with values in FieldOne and then do the GroupBy. In the UI grid, the records with FieldOne values are missing. I want to only group the records with empty FieldOne values and still have the records with FieldOne values. Thanks.
MyDataAsEnumerable()
.Where(f => f.Field<string>("FieldOne") == null)
.GroupBy(r => new { pp1 = r.Field<int>("FirstId") })
.Select(g => g.First())
.CopyToDataTable();
You could make an artifical grouping key:
.GroupBy(
r => new { pp1 = f.Field<string>("FieldOne") == null ? -1 : r.Field<int>("FirstId") })
Here, I used -1 as a hack to create a separate group. Make sure this int value is not in use. You could also solve this precisely but hopefully this is OK.

Get complex object using IN equivalent in LINQ

I have a list of type customer. I need to insert all values of the list in the database before checking if a customer with the same customer number exists for that particular client.
For that I am firing a query to get me all customers who are there in the database having customer number equal to ones in the list. The query I am writing is not working, here's the code.
CustomerRepository.Find(x => x.ClientId == clientId)
.Where(x => x.CustomerNumber.Contains(lstCustomersInserted.Select(c => c.CustomerNumber)));
Keep it simple:
var lstCustomerNumbers = lstCustomersInserted.Select(c => c.CustomerNumber);
var res = CustomerRepository.Where(x => x.ClientId == clientId && lstCustomerNumbers.Any(c => c == x.CustomerNumber));
I think you have it backwards. Try reversing the Contains.
Edit: I switched to using the generic predicate Exists instead of Contains based on the comment, so you can match a property.
CustomerRepository.Find(x => x.ClientId == clientId)
.Where(x => lstCustomersInserted.Exists(c => x.CustomerNumber == c.CustomerNumber));
How about an Except?
CustomerRepository.Select(x => x.ClientID)
.Except(lstCustomersInserted.Select(x => x.CustomerID));
This will return the IDs of the objects in the repo that don't exist in your lstCustomersInserted.

Chained selects with where at the end

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.

Categories

Resources