score:0
After piecing together information from a lot of different sources -- none of which dealt with the exact circumstances of the problem that I am having, I've come to the following conclusion:
When querying SharePoint data using the SharePoint Object Model and Collaborative Application Markup Language (CAML), SharePoint by default does not use the time component of DateTime elements when doing comparisons. To tell SharePoint to use the time component, you must include the IncludeTimeValue = 'TRUE' property on the value type as shown here:
<Where>
<Eq>
<FieldRef Name='Begins' />
<Value Type='DateTime' IncludeTimeValue='TRUE'>
2008-03-24T12:00:00Z
</Value>
</Eq>
</Where>
I found several blog posts that referenced a bug in LINQ to SharePoint that caused the generated CAML to be output as:
<Where>
<Eq>
<FieldRef Name='dateTimeField' IncludeTimeValue='TRUE' />
<Value Type='DateTime'>
2008-03-24T12:00:00Z
</Value>
</Eq>
</Where>
Notice that the IncludeTimeValue = 'TRUE' is on the FieldRef element instead of the Value element. Since this is not the right place for that property, it causes all LINQ to SharePoint queries that perform datetime comparisons to only compare on the date component.
Since I am seeing that exact same behavior when using LINQ and WCF Data Services to connect to SharePoint, I can only assume that under the covers LINQ/WCF Data Services is producing the same invalid CAML.
The solution (assuming I still want to use LINQ/WCF Data Services) is to perform two queries (as stated in the original question). The first LINQ query pulls the list data from SharePoint and stores it in a List. The second LINQ query handles the date comparisons to only pull the data I want.
Since in my particular circumstance, I may have many entries in the SharePoint list covering a large time span but will only be interested in entries on a particular day or couple of days, I wanted to find a way not to bring back the entire list in the first query.
What I settled on was doing a <= and >= comparison to get close, and then further limiting that in my second query. So my two queries now become:
DateTime RightNow = DateTime.Now;
var query = (from a in context.Alerts
where (a.Begins <= RightNow) && (a.Expires >= RightNow)
select a).ToList();
var query2 = from q in query
where q.Begins < RightNow) && (a.Expires > RightNow)
select q;
The first LINQ statement will return all the items that I am ultimately interested in; along with a few that I'm not (because it's comparing just the date component of the datetime). The second LINQ statement will further pare that down to just those that I'm interested in.
score:0
Is DateTime.Today getting used in there somewhere? I did some prototyping with LinqPad, and the only way to duplicate your results was if I had the query using "where (a.Begins < DateTime.Today)"
Here's the quick sketch I did of what it sounds like you're describing:
void Main()
{
List<Alerts> alerts = new List<Alerts>();
alerts.Add(new Alerts(DateTime.Now.AddDays(-1)));
alerts.Add(new Alerts(DateTime.Now));
var query = from a in alerts
where (a.Begins < DateTime.Now)
select a;
foreach (var element in query)
{
Console.WriteLine(element.Begins);
}
}
public class Alerts
{
public DateTime Begins {get; set;}
public Alerts(DateTime begins)
{
Begins = begins;
}
}
As I mentioned, the only way to duplicate your described results was if I changed DateTime.Now to DateTime.Today in the where clause. I would look through your code for accidental usages of the wrong DateTime method.
As an aside, I HIGHLY recommend using LinqPad for prototyping your Linq queries... It can save you time by allowing you to quickly iterate over your code and figure out what your trouble spots are. Also, it's very much worth the $50 for intellisense and other premium features.
score:0
I can confirm the bug with SharePoint 2010 LINQ to SharePoint not creating the correct CAML (adding IncludeTimeValue='True' to the FieldRef instead of the Value) is fixed by the October 2013 Cumulative Update to SharePoint Foundation 2010. The hotfix can be downloaded from http://technet.microsoft.com/en-us/sharepoint/ff800847.aspx.
The same bug exists also in SharePoint 2013 which I was informed by Microsoft support should be fixed in the December 2013 Cumulative Update to SharePoint Foundation 2013, but I cannot confirm this. I was informed that the fix is also deployed to Office 365, but I cannot confirm this.
score:1
I have not used SharePoint 2010's OData. However, when querying against the SharePoint 2010 object model, the anomaly you posted is a common behavior, re: you must convert the query to a list before you can query the data.
The typical pattern here is to:
var query = someSharePointQuery.ToList();
var results = query.Where(...).First(...);
Seems odd, but this is how SP 2010 seems to work.
score:2
For a Linq to SharePoint query that needs to include the time element of the DateTime you can use TimeOfDay.
var next_slots = (from s in dc.HRDates
where
s.StartTime.HasValue &&
s.StartTime.Value.Date == appt.Value.Date &&
s.StartTime.Value.TimeOfDay == appt.Value.TimeOfDay
...
Source: stackoverflow.com
Related Query
- Using date comparison in LINQ when querying SharePoint OData service
- How to reuse a linq expression for 'Where' when using multiple source tables
- Avoiding code repetition when using LINQ
- Return Count from Netflix oData Service When the LINQ Count() Method Doesn't Work
- Class has invalid expression term "from" when querying using LINQ
- Range variable name cannot match the name of a member of the 'Object' class. when querying a DataGridView using Linq
- Error When Querying For A Substring Using Dynamic Linq
- Linq sub query when using a repository pattern with EF code first
- Linq group by date when using multiple group by fields
- How can I check the number of calls to the database in LINQ query when using .NET Core and Code First?
- alternate of join in OData Service using linq
- Only check date condition when DateTime?(nullable?) using LINQ
- When querying a collection using linq it always returns a null
- Update & Insert into database using Odata service and linq
- When querying a collection using linq it always returns a null
- date format not correct when pulling from database using linq query
- Location of XElement when querying over IEnumerable using LINQ
- Updating List using LINQ working when execute from Immediate window, not from code direct
- Getting InvalidCastException when trying to implement sorting in Entity Framework Code First using Linq
- NullReferenceException when querying Ids using LINQ and Contains
- Querying the database using EF Code First and Linq
- Querying values using OData and LINQ that contain '<' and '>' characters
- Convert string[] to int[] in one line of code using LINQ
- Entity-framework code is slow when using Include() many times
- Ambiguous call when using LINQ extension method on DbSet<T>
- How to handle nulls in LINQ when using Min or Max?
- How to avoid Query Plan re-compilation when using IEnumerable.Contains in Entity Framework LINQ queries?
- Why does this Linq Cast Fail when using ToList?
- Why does C# compiler create private DisplayClass when using LINQ method Any() and how can I avoid it?
- What actually happens when using async/await inside a LINQ statement?
More Query from same tag
- When IQueryable returns no record ToList() throws an exception
- For vs. Linq - Performance vs. Future
- how to get table data in json using linq and entityframework
- Casting to custom type, Enumerable.Cast<T> and the as keyword
- Error in MVC Linq
- Linq to Sql : how to get data - one to many
- Store entire table then loop through it in the view
- LINQ equivalent of foreach for IEnumerable<T>
- Is there a better way to force LINQ-TO-SQL string comparison to be Case Insensitive?
- How to simplify repetitive OR condition in Where(e => e.prop1.contains() || e.prop2.contains() || ...)
- Using into and from in Linq query
- LINQ: How to return different field than used by min()
- LINQ: Relations do not get updated after SubmitChanges and Refresh
- Writing a Simple LINQ Query
- return the first longest string consisting of n consecutive strings taken in the array in c#
- How can I create an Action<T> in F#?
- How to insert to database in bulk instead of inserting it 1 by 1
- LINQ inserts 'ESCAPE N'~' in query
- Return filtered collection of results
- DATETIME Error(Finding total days)
- Is it possible to accelerate (dynamic) LINQ queries using GPU?
- FInding sum of values in a column for each identical other columns in a list
- Runtime Generated EventHandler of Unknown Type
- get associated records in ms dynamics crm
- Group dictionary by multiple properties of key
- Access to LINQ results - what is a better way?
- LINQ object of IEnumerable type does not return a DataTable
- Dynamic sorting with nullable column
- How do I use LINQ to get all the Items that have a particular SubItem?
- Hashset Concatenate using Linq