-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrong translation for default(DateTime)/default(Guid)/default(TimeSpan) in linq projection #24075
Comments
var connection = db.Database.GetDbConnection();
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT '0001-01-01T00:00:00.0000000'";
using (var reader = command.ExecuteReader())
{
reader.Read();
Console.WriteLine(reader.GetDataTypeName(0));
Console.WriteLine(reader.GetDateTime(0));
}
}
connection.Close(); The issue is in SqlClient which doesn't return correct type. The datatype is |
@smitpatel are you sure there's a SqlClient issue here? It seems pretty reasonable to me for this untyped literal to return a varchar (anything else would require sniffing and heuristically inferring the type based on contents). Shouldn't we be typing the literal in this case, i.e. |
Other providers are working fine with the query. The untyped literal is how datetimes are printed in SQL for SqlClient so if a literal can be interpreted in multiple different types then there should be resiliency. |
FWIW the code above also fails on Npgsql ( So yeah, I think that if we want to make this work, we're going to need that convert node. It's also a bit odd to roundtrip an uncorrelated value like this, I wonder if there's an actual use case... |
Consider we have an entity type like this: public class Person
{
public int Id { get; set; }
public DateTime Birthday { get; set; }
//Omit other properties
} Only the users who have permisson can access The query is like this: bool currentUserCanAccessBirthdayProperty = true; // or false
var persons = db.People.Select(x => new Person
{
Id = x.Id,
Birthday = currentUserCanAccessBirthdayProperty ? x.Birthday : default(DateTime)
}) If
We use OData to shape the returned entities, so it's not possible to set I know that changing the type of |
I agree. It's better to handle 'default(DateTime)' at the client side. But making a convert node is also ok. |
@anranruye thanks for the use-case scenario, that makes sense. On an unrelated note, for your example, it could be argued that the type mapping of x.Birthday should be used to generate the literal for |
Note from triage: we may be able to do something similar to what we do for spatial types. Then again, we may not. Brice to take a look. |
Here is a workaround: bool currentUserCanAccessBirthdayProperty = true; // or false
DateTime defaultDateTime = default(DateTime);
var persons = db.People.Select(x => new Person
{
Id = x.Id,
Birthday = currentUserCanAccessBirthdayProperty ? x.Birthday : defaultDateTime
}) In fact, I already mentioned this in the original post:
|
This has come up again for the SQL Server bool/bit mapping - the literal representation Stepping back...
|
Cast is not unnecessary for all non-projection cases. When types are not implicitly convertible without loss, explicit cast is needed. So #15586 is unavoidable. |
@smitpatel which scenario do you have in mind (can you give an example)? |
Note this "interesting" case on SQL Server: -- The following works fine:
SELECT CAST('2020-01-01 12:00' AS datetime2) AT TIME ZONE 'W. Europe Standard Time';
-- The following errors: Argument data type varchar is invalid for argument 1 of AT TIME ZONE function
SELECT '2020-01-01 12:00' AT TIME ZONE 'W. Europe Standard Time'; So this is another (odd) scenario where explicit SQL typing needs to be added. At this point I'm just doing it in the method translator in #27168. |
I've also just run into this. For anyone else looking for a workaround, adding dbContext.Set<AnyEntityType>().Select(x => new
{
DateTime = (DateTime)(object)DateTime.MinValue,
x.SomeProperty
}).ToList(); SQL SELECT CAST('0001-01-01T00:00:00.0000000' AS datetime2) AS [DateTime], [x].[SomeProperty]
FROM [TableName] AS [x] |
Same things happens when you configure a DateTime class field to be mapped to a column on SQL Server with type When applying a migration that would create that column and set default values, you would have an error message about invalid casting from varchar to datetime. |
I saw this issue too late and created another reproduction, this time with Guids being serialized as string into the query and then not being read back in correctly. https://github.com/Tragetaschen/efcore-nullable-guid-string |
How to reproduce:
Expected result:
One of:
default(DateTime)
like a variabledefault(DateTime)
DateTime
typeActual result:
Generated sql:
EF Core version: 5.0.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 5.0
Operating system: Windows 10
IDE: Visual Studio 2019 16.8
The text was updated successfully, but these errors were encountered: