I am trying to take a DateTime value, and if it is not null return the Short Time String. My query looks like this: (TimeIn is NOT NULLABLE, whereas TimeOut is NULLABLE)
var times = from t in db.TimePostings
where t.MemberID == member.MemberID
select new
{
Date = t.TimeIn.ToShortDateString(),
TimeIn = t.TimeIn.ToShortTimeString(),
TimeOut = t.TimeOut.HasValue ? t.TimeOut.Value.ToShortTimeString() : "-------"
};
gvTimePostings.DataSource = times;
gvTimePostings.DataBind();
but this fails when I try to databind with the error:
Could not translate expression 'Table(TimePosting).Where(t => (t.MemberID == Invoke(value(System.Func
1[System.String])))).Select(t => new <>f__AnonymousType8
4(Date = t.TimeIn.ToShortDateString(), TimeIn = t.TimeIn.ToShortTimeString(), TimeOut = IIF(t.TimeOut.HasValue, (t.TimeOut ?? Invoke(value(System.Func`1[System.DateTime]))).ToShortTimeString(), "-------"), Hours = ""))' into SQL and could not treat it as a local expression.
I also get a similar error if I try to use:
TimeOut = t.TimeOut.HasValue ? Convert.ToDateTime(t.TimeOut).ToShortTimeString() : "-------"
however, if I change the TimeOut property to:
TimeOut = t.TimeOut.HasValue ? t.TimeOut.ToString() : "-------",
it works fine, but does not format the time like I want it (shortTimeString).
what's up with that?
As others have said, the problem is with trying to convert ToShortDateString
etc to SQL. Fortunately, this is easy to fix: fetch the data with SQL, then format it in .NET:
var timesFromDb = from t in db.TimePostings
where t.MemberID == member.MemberID
select new { t.TimeIn, t.TimeOut };
var times = from t in timesFromDb.AsEnumerable()
select new
{
Date = t.TimeIn.ToShortDateString(),
TimeIn = t.TimeIn.ToShortTimeString(),
TimeOut = t.TimeOut.HasValue
? t.TimeOut.Value.ToShortTimeString()
: "-------"
};
The call to AsEnumerable()
here basically means, "stop trying to process the query using SQL; do the rest in LINQ to Objects".
ToShortTimeString()
has no translation in SQL. Because of that, converting the statement into a single SQL statement fails and the exception is thrown.
If you break the statement into two calls (one to retrieve the data and another to create the projection), things will work just fine:
// must call ToList to force execution of the query before projecting
var results = from t in db.TimePostings
where t.MemberID == member.MemberID
select new { t.TimeIn, t.TimeOut };
var times = from t in results.AsEnumerable()
select new
{
Date = t.TimeIn.ToShortDateString(),
TimeIn = t.TimeIn.ToShortTimeString(),
TimeOut = t.TimeOut.HasValue ?
t.TimeOut.Value.ToShortTimeString() :
"-------"
};
Have you tried:
TimeOut = t.TimeOut.HasValue ? t.TimeOut.ToString("d") : "-------",
This will normally give the short format of the DateTime
. Whether it works or not will depend on whether it can be translated to SQL or not.
If it doesn't work you'll have to break the query into two parts. The first gets the data, the second format it. You'll have to convert the first query to a list (.ToList()
) to force the SQL to be evaluated.
Simply, it's not supported by this specific linq provider.
Your linq query is converted into an expression tree. It is up to the SQL Linq provider to convert this expression tree into SQL. Understandably, it does not have the capability to translate every single .NET function.
Your solution is to explicitly run the SQL by calling ToArray
or ToList
, and then allow LinqToObjects to handle the rest.
var times = from t in db.TimePostings
where t.MemberID == member.MemberID
select new {
TimeIn = t.TimeIn,
TimeOut = t.TimeOut
};
var timesFormated = times.ToArray() // Runs the query - any further processing will be run in memory by the local .NET code
.Select(t => new {
Date = t.TimeIn.ToShortDateString(),
TimeIn = t.TimeIn.ToShortTimeString(),
TimeOut = t.TimeOut.HasValue ? t.TimeOut.Value.ToShortTimeString() : "-------",
Hours = ""
}
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With