Sto usando Microsoft.EntityFrameworkCore.SqlServer v2.1.2 (e ho anche provato v2.2.0-preview1-35029) e sto usando LINQ per recuperare una raccolta di entità da un database Azure SqlServer, filtrando su un campo DateTime.
Tuttavia, l'SQL generato dall'istruzione LINQ utilizza un valore DateTime basato su stringa che SqlServer rifiuta con questo errore:
Conversione non riuscita durante la conversione di data e / o ora dalla stringa di caratteri.
Posso modificare l'istruzione SQL per modificare il formato datetime in modo che la query funzioni senza errori (vedi sotto per i dettagli), ma non so come ottenere il framework per generare lo stesso formato datetime.
Mentre EntityFrameworkCore è ancora un po 'nuovo, sembra che questo sia un caso d'uso piuttosto semplice, quindi presumo che stia facendo qualcosa di sbagliato e che non sia un problema di framework.
Come impedire a EF di generare un valore datetime non valido nell'SQL?
e / o
Come posso ottenere l'SQL generato per utilizzare un altro formato per gli oggetti DateTime?
Il modello EntityFramework che sto usando assomiglia a questo:
public class DeskReading
{
public int DeskReadingId { get; set; }
//... some other fields ...
public DateTime Timestamp { get; set; }
}
E il mio LINQ per interrogare i valori assomiglia a questo:
IQueryable<DeskReading> readings =
_dbContext.DeskReadings
.OrderBy(gr => gr.Timestamp)
.Where(gr => gr.Timestamp > new DateTime(2017, 05, 01));
readings.ToList();
E l'SQL generato da questo assomiglia a questo:
SELECT [gr].[DeskReadingId] --...some other fields ...
FROM [DeskReadings] AS [gr]
WHERE [gr].[Timestamp] > '2017-05-01T00:00:00.0000000'
ORDER BY [gr].[Timestamp]
Si noti che il valore per il filtro è '2017-05-01T00:00:00.0000000'
Se eseguo quell'SQL direttamente su SqlServer tramite SSMS, ottengo lo stesso errore:
Ma se cambio il filtro per usare '2017-05-01 00:00:00'
, funziona bene:
SELECT [gr].[DeskReadingId] --...some other fields ...
FROM [DeskReadings] AS [gr]
WHERE [gr].[Timestamp] > '2017-05-01 00:00:00'
ORDER BY [gr].[Timestamp]
Come richiesto, ecco lo script di creazione per la tabella:
CREATE TABLE [dbo].[DeskReadings](
[DeskReadingId] [int] IDENTITY(1,1) NOT NULL,
[SoilMoistureSensor1] [int] NOT NULL,
[SoilMoistureSensor2] [int] NOT NULL,
[LightLevel] [int] NOT NULL,
[TemperatureF] [real] NOT NULL,
[HumidityPercent] [real] NOT NULL,
[Timestamp] [datetime] NOT NULL,
CONSTRAINT [PK_dbo.DeskReadings] PRIMARY KEY CLUSTERED
(
[DeskReadingId] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
Nell'osservare il codice sorgente su GitHub , esiste una formattazione condizionale che EntityFrameworkCore utilizza in base a StoreType e ritiene che la colonna dell'espressione sia. Ad esempio, il formato visualizzato è chiaramente per datetime2
. L'errore che si verifica può verificarsi quando si confronta una colonna datetime
con una stringa formattata datetime2
.
Ecco la fonte a cui mi riferisco, ci sono tre string consts che rappresentano il formato per il valore di C # DateTime
:
private const string DateFormatConst = "{0:yyyy-MM-dd}";
private const string DateTimeFormatConst = "{0:yyyy-MM-ddTHH:mm:ss.fffK}";
private const string DateTime2FormatConst = "{0:yyyy-MM-ddTHH:mm:ss.fffffffK}";
Logica condizionale https://github.com/aspnet/EntityFrameworkCore/blob/release/2.2/src/EFCore.SqlServer/Storage/Internal/SqlServerDateTimeTypeMapping.cs#L70-L74
Per risolvere questo problema specifico, puoi attribuire il tuo modello come tale:
public class DeskReading
{
public int DeskReadingId { get; set; }
[Column(TypeName="datetime")]
public DateTime Timestamp { get; set; }
}
Ciò StoreType
confronti per trattarlo come un StoreType
di datetime
e formattarlo correttamente.