Using date field comparisons in RavenDB LINQ queries - c#

In RavenDB, I would like to query the database using a date field. How can I write a LINQ query to query the RavenDB that involves date comparison..
Session.Query<Movie>()
.Where(x => x.Status == "New" && x.ReleaseDate > DateTime.Parse("04/03/2012 00:00:00"))
.Dump();
is returning zero records inm LINQ pad. Something is not right the way I wrote the query.. thanks for any help.

Instead of DateTime.Parse() try instantiating a new DateTime.
Session.Query<Movie>()
.Where(x => x.Status == "New" && x.ReleaseDate > new DateTime(2012, 4, 3))
.Dump();

Related

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

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

Which one is faster? Sort data in IQueryable or IEnumerable?

I have a table with more than 600 millions rows. I have a query (like turnover report query) that select portions of the table (maximum 5% of all data filtered by RegDate condition). I want to sort results of this query.
I use indexes on Id and RegDate columns. Which one is faster? Sort data in IQueryable or IEnumerable?
var activites = _turnOverRepository.GetTransactions(account.Id)
.Where(a => a.RegDate >= fromDate && a.RegDate <= toDate)
.OrderBy(a => a.RegDate)
.ThenBy(a => a.RegTime)
.ToList();
OR
var activites = _turnOverRepository.GetTransactions(account.Id)
.Where(a => a.RegDate >= fromDate && a.RegDate <= toDate)
.ToList();
.OrderBy(a => a.RegDate)
.ThenBy(a => a.RegTime)
It's fastest to sort in the database using IQueryable if you have the correct index in place. That's because there's a rule about sorting, where the fastest sort happens on already sorted data. The index will sort the data on insert.
Create a single composite index on (Id, RegDate, RegTime).

How can I improve this EF query?

C# on .NET 3.5 Framework
So, I'm trying to make an efficient query to find all emails to purge from my system. What should be purged are emails that have been attempted (Datetime column LastAttempted is not null) and the # of days to retain (int column RetentionDays) has elapsed. This works, but I know it's pulling everything back and filtering in memory.
This is what I have right now
var emails = dbContext.Emails
.Where(x => x.LastAttempted.HasValue == true)
.ToList()
.Where(x => ((DateTime)x.LastAttempted).AddDays(x.RetentionDays) <= DateTime.Now);
How can I update this so it only pull the records I'm caring about from SQL Server?
Use EntityFunctions.AddDays to add days to a DateTime in an EF query.
var emails = dbContext.Emails
.Where(x => x.LastAttempted.HasValue &&
EntityFunctions.AddDays(x.LastAttempted, x.RetentionDays)
<= DateTime.Now);
This part of query:
dbContext.Emails
.Where(x => x.LastAttempted.HasValue == true)
.ToList();
will be executed in the sql server and an in memory collection will be returned, when ToList is called.
Then the last part of your query:
.Where(x =>
((DateTime)x.LastAttempted).AddDays(x.RetentionDays) <= DateTime.Now);
will be executed in the items of the above mentioned in memory collection.
So the problem relies on the last part of your query. You could avoid this using the method AddDays of EntityFunctions and avoid making the second filtering in the in memory collection. This can be done like below:
dbContext.Emails
.Where(x => x.LastAttempted.HasValue == true &&
EntityFunctions.AddDays(x.LastAttempted, x.RetentionDays)
<= DateTime.Now);
Move ToList() at the end of the query
var now = DateTime.Now;
var emails = dbContext.Emails
.Where(x => x.LastAttempted.HasValue &&
EntityFunctions.AddDays((DateTime)x.LastAttempted, x.RetentionDays) <= now).
ToList();
You can always query the database directly, like this:
var items = dbContext.Database.SqlQuery<Email>("select * from Emails where LastAttempted Is Not Null And LastAttempted + RetentionDaya >= GetDate()", new SqlParameter[0]);
NOTE: I made some guesses with respect to your entity, table, and column names.

Comparing the dates logic in Linq

I want to query the result
public resultType GetData(int ClientID, DateTime CreatedDate)
{
var Row = DB.tblPlans
.Where(m => m.fkClient_Id == ClientID && m.PlanDate <= CreatedDate)
.OrderByDescending(m => m.Id)
.FirstOrDefault();
}
But the results are not coming as required because the "m.PlanDate" in the query is comparing the time also.
so The parameter "CreatedDate" in the above function will always get "12:00:00 AM" attached to it suppose "2/17/2014 12:00:00 AM"
because it is a datepicker control and I am converting it into datetime but the value of created date with which I have to compare it is having original timing suppose "2/17/2014 11:58:35 AM"
and that is why I am not getting the desired result.
I think the result will be fine if time portions get removed.
I have searched the above problem and it have many solutions like::
using AddDays(1); but I am not sure about it's working.
also I tried::
http://www.codeproject.com/Articles/499987/LINQ-query-to-compare-only-date-part-of-DateTime
Please suggest me a better way to do this as this is not the first time I am getting this problem.
If you are using Linq to SQL (as you specified in question tag), then simply get Date part of DateTime:
var Row = DB.tblPlans
.Where(m => m.fkClient_Id == ClientID && m.PlanDate.Date <= CreatedDate)
.OrderByDescending(m => m.Id)
.FirstOrDefault();
With Entity Framework you should use EntityFunctions.TruncateTime(m.PlanDate)
Have you tried this:
public resultType GetData(int ClientID, DateTime CreatedDate)
{
var Row = DB.tblPlans
.Where(m => m.fkClient_Id == ClientID && m.PlanDate.Date <= CreatedDate)
.OrderByDescending(m => m.Id)
.FirstOrDefault();
}
The recommended way to compare dates in linq queries if you are using EntityFramework 6 is DbFunctions.TruncateTime(m.PlanDate) and for previous versions EntityFunctions.TruncateTime(m.PlanDate)

How to implement SkipWhile with Linq to Sql without first loading the whole list into memory?

I need to order the articles stored in a database by descending publication date and then take the first 20 records after the article with Id == 100.
This is what I would like to do with Linq:
IQueryable<Article> articles =
db.Articles
.OrderByDescending(a => a.PublicationDate)
.SkipWhile(a => a.Id != 100)
.Take(20);
However, this generates a NotSupportedException because SkipWhile is not supported in Linq to Sql (see here).
A possible solution is to execute the query and then apply SkipWhile using Linq to Object:
IEnumerable<ArticleDescriptor> articles =
db.Articles
.OrderByDescending(a => a.PublicationDate)
.ToList()
.SkipWhile(a => a.Article.Id != 100)
.Take(20);
But this means I need to load the whole ordered list into memory first and then take 20 articles after the one with Id == 100.
Is there a way to avoid this huge memory consumption?
More in general, what is the best way to achieve this in SQL?
If, as I'm guessing from the column name, PublicationDate doesn't change, you can do this in two separate queries:
Establish the PublicationDate of the Article with Id == 100
Retrieve the 20 articles from that date onwards
Something like:
var thresholdDate = db.Articles.Single(a => a.Id == 100).PublicationDate;
var articles =
db.Articles
.Where(a => a.PublicationDate <= thresholdDate)
.OrderByDescending(a => a.PublicationDate)
.Take(20);
It might even be that LINQ to SQL can translate this:
var articles =
db.Articles
.Where(a => a.PublicationDate
<= db.Articles.Single(aa => aa.Id == 100).PublicationDate)
.OrderByDescending(a => a.PublicationDate)
.Take(20);
but that may be too complex for it. Try it and see.
You can try like this
var articles =
db.Articles
.Where(a => a.PublicationDate < db.Articles
.Where(aa => aa.Id==100)
.Select(aa => aa.PublicationDate)
.SingleOrDefault())
.OrderByDescending(a => a.PublicationDate)
.Take(20);
Isnt the solution to just add a where statement?
IQueryable<Article> articles = db.Articles.Where(a => a.id != 100).OrderByDescending(a => a.PublicationDate).Take(20);

Categories

Resources