Visual Studio/LINQ syntax with a database field called 'date' - linq

I am building a new VB.net MVC5 front-end for an existing database. I am constructing the LINQ queries to interrogate the DB through EF6.
One of the tables has a field called 'date' - when I try and construct the LINQ query in VS2013 the UI refuses to recognise the field 'date' as being from the table:
Dim a = From e In db.events
Select New Models.Tasks With {.TaskID=enq, .Title=task_name, .StartDate=Date}
In VS2013 the final curly bracket is underlined (". expected") - the UI not recognising 'Date' as a field in db.events
Is there a workaround for this issue?

Related

EF Core to SQL group by date without time can't be translated to SQL

Using .NET 6 and EF Core, I have this code:
var FileSizeMB_Grouped =
_db.FileSizeMBs.GroupBy(x => x.CreatedDate.Date);
I get this error from it:
The LINQ expression 'DbSet().GroupBy(x => x.CreatedDate.Date)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
I know the reason, if I use .AsEnumerable(), it works fine because can't be translated to SQL, but...
Is there any way to translate this to SQL directly without using AsEnumerable or RawSqlQuery ?
I have read a lot of posts like these:
DbFunctions.TruncateTime LINQ equivalent in EF CORE
How to compare DateTime without time via LINQ?
But...
.Date property can't be translated
DbFunctions.TruncateTime can't be found
Microsoft.EntityFrameworkCore.EF.Functions can't be found
EF.Property<DateTime>(x.CreatedDate, "dt").Date can't be translated

how to remove a character at the end of a string in linq c#

I have the following LINQ query; I want to remove dot character if available at the end of string
var hatoList = (from L in db.vHatoList select L.HatoFullName.Trim('.')).ToList();
You're currently trying to perform the query in the database. We don't know what database technology you're using, so it's hard to know whether there's some way to make it actually happen in the database, but it's probably simplest to do in memory instead (given that it won't change how many records will be returned). The AsEnumerable() method is used to just change the compile-time type to IEnumerable<T> (instead of IQueryable<T>) forcing the rest of the query to be evaluated in .NET code instead of in the database:
var hatoList = db.vHatoList
.AsEnumerable()
.Select(entry => entry.HatoFullName.TrimEnd('.'))
.ToList();
(I've also changed the call from Trim to TrimEnd to avoid it removing periods at the start of the string.)
You are using linq to sql and database does not understand TrimEnd or Trim.
So first you have need to load data in memory and then use TrimEnd method.
var hatoList = (from L in db.vHatoList select L.HatoFullName).ToList().
Select(t=>t.TrimEnd('.'));

Lightswitch 2013 Linq queries to Get min value

I'm writing a timesheet application (Silverlight) and I'm completely stuck on getting linq queries working. I'm netw to linq and I just read, and did many examples from, a Linq book, including Linq to Objects, linq to SQl and linq to Entities.(I assume, but am not 100% sure that the latter is what Lightswitch uses). I plan to study a LOT more Linq, but just need to get this one query working.
So I have an entity called Items which lists every item in a job and it's serial no
So: Job.ID int, ID int, SerialNo long
I also have a Timesheets entity that contains shift dates, job no and start and end serial no produced
So Job.ID int, ShiftDate date, Shift int, StartNo long, EndNo long
When the user select a job from an autocomplete box, I want to look up the MAX(SerialNo) for that job in the timesheets entity. If that is null (i.e. none have been produced), I want to lookup the MIN(SerialNo) from the Items entity for that job (i.e. what's the first serial no they should produce)
I realize I need a first or default and need to specify the MIN(SerialNo) from Items as a default.
My Timesheet screen uses TimesheetProperty as it's datasource
I tried the following just to get the MAX(SerialNo) from Timesheets entity:
var maxSerialNo =
(from ts in this.DataWorkspace.SQLData.Timesheets
where ts.Job.ID == this.TimesheetProperty.Job.ID
select ts.StartNo).Min();
but I get the following errors:
Instance argument: cannot convert from 'Microsoft.LightSwitch.IDataServiceQueryable' to 'System.Collections.Generic.IEnumerable
'Microsoft.LightSwitch.IDataServiceQueryable' does not contain a definition for 'Min' and the best extension method overload 'System.Linq.Enumerable.Min(System.Collections.Generic.IEnumerable)' has some invalid arguments
I also don't get why I can't use this:
var maxSerialNo = this.DataWorkspace.SQLData.Timesheets.Min(ts => ts.StartNo);
Can anyone point me in the right direction?
Thanks
Mark
IDataServiceQueryable doesn't support full set of LINQ operator like IEnumerable has.
IDataServiceQueryable – This is a LightSwitch-specific type that allows a restricted set of “LINQ-like” operators that are remote-able to the middle-tier and ultimately issued to the database server. This interface is the core of the LightSwitch query programming model. IDataServiceQueryable has a member to execute the query, which returns results that are IEnumerable. [Reference]
Possible solution is, execute your query first to get collection of type IEnumerable by calling .ToList(), then you can call .Min() against the first query result. But that isn't good idea if you have large amount of data, because .ToList() will retrieve all data match the query and do further processing in client side, which is inefficient.
Another way is, change your query using only operators supported by IDataServiceQueryable to avoid retrieving unnecessary data to client. For example, to get minimum StartNo you can try to use orderby descending then get the first data instead of using .Min() operator :
var minStartNo =
(
from ts in this.DataWorkspace.SQLData.Timesheets
where ts.Job.ID == this.TimesheetProperty.Job.ID
orderby ts.StartNo descending select ts
).FirstOrDefault();

How to obtain column metadata from linq to Entities query?

I need to support legacy client and compose ADO datasets from our Linq queries. The problem is how get specific column information (varchar length, decimal precision, etc) that cannot be obtained using reflection.
for example, I have table Customer with field Name varchar(80)
When I fetch data from linq to entities query:
var data = (from c in ctx.Customers select c.Name).ToList()
I cannot obtain maxSize for the column data[i].Name and adodataset raises an error.
I already have simple solution:
Code to extract column metadata from ObjectContext by property reference
Simple code that parses expression from Queryable and links output properties to edm columns.
But I have a lot of issues parsing complex queries that include multiple nested groupbys/unions/joins etc.
Does anybody know any other way (maybe using materialization shaper or similar)?
Thanks to EFProviderWrappers by Joseph Kowalski I have made similar provider and published it on codeplex

Using date comparison in LINQ when querying SharePoint OData service

ANSWERED: Go below to find my answer to this question.
I am trying to consume SharePoint 2010 OData from an ASP.NET MVC 3 project using LINQ. I created a default project using the ASP.NET MVC 3 project template with the Razor view engine (VS 2010). I added a service reference pointing to my SharePoint 2010 site.
In my HomeController's Index method (this is just a test project), I created a variable to hold the context and set the Credentials property of the context variable to the current default credentials.
A link query like the following works fine and I can use the created variable to access any of the data:
var query = from a in context.Alerts
select a;
This query simply gets all of the announcements from a list called Alerts in the SharePoint site. This list has fields for the Title, Content, Beginning Date, and Expiration Date.
When I change the query to the following, I do not get the expected results:
var query = from a in context.Alerts
where (a.Begins < DateTime.Now)
select a;
This query ignores the time component of the date. For example, if a.Begins contains a datetime from yesterday, the query returns the AlertItem. If on the other hand, a.Begins contains a datetime with the current date (but an earlier time) the comparison returns false (and a.Begins == DateTime.Now returns true).
If I do the following, the second LINQ query works as expected:
var query = (from a in context.Alerts
select a).ToList();
var query2 = from q in query
where (q.Begins < DateTime.Now)
select q;
What am I missing?
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
...
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.
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.
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.
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.

Resources