Entity Framework und DateTime-Vergleich mit Millisekunden-Genauigkeit

8

Ich habe ein Problem mit Entity Framework (Code First) unter C # bezüglich des Vergleichs von DateTime-Werten. Ich verwende die unten definierte Klasse Validity (vereinfacht für dieses Beispiel) als eine Oberklasse von anderen Entitäten, die eine definierte Gültigkeit in der Zeit haben soll.

%Vor%

In den letzten drei Zeilen finden Sie die Klasse "Item", die wir als Beispiel nehmen werden. Werfen wir einen Blick auf diese Abfrage:

%Vor%

Diese Abfrage sollte nur Rückgabeobjekte der Klasse Item zurückgeben, die bei "requestTime" "gültig" sind. Beachten Sie, dass für ValidTo == requestTime das Item als "ungültig" zu betrachten ist (die Zeitspanne ValidFrom zu ValidTo ist -exclusive- ValidTo; siehe Kommentare im Quellcode oben).

Das Problem

Ich habe tatsächlich - have - Ergebnisse in meinen Ergebnismengen "items" mit ValidTo == requestTime . Ich habe das gerade über

überprüft %Vor%

** HINWEIS: Dieser Fehler tritt nicht selten auf, sondern fast immer in der Software als .inValidate (requestTime); wird oft aufgerufen, um ein Objekt zu entwerten. **

Ich habe manuell über Microsoft SQL Server Management Studio (Microsoft SQL Server 2008 wird als Backend verwendet) die erzeugte SQL-Abfrage von LinQ überprüft. Ich musste @ p__linq__0, @ p__linq__1 selbst deklarieren / setzen (was beides requestTime bedeutet) ...

%Vor%

Dies funktioniert tatsächlich wie erwartet. Aber wenn ich '2012-10-23 15:15:11' stattdessen als Wert verwende, erhalte ich (wie erwartet) falsche Ergebnisse. Sie sind denen in meinem Programm ähnlich. Also ich denke, das ist das Problem ...

In Database hat die "DateTime" Millisekunden definiert und ValidFrom / ValidTo einschließlich Millisekunden gespeichert. Aber ich nehme an, dass die Abfrage den Millisekunden-Teil des Zeitstempels aus irgendeinem Grund nicht enthält ... Die variable requestTime hat jedoch den Millisekunden-Wert festgelegt.

Leider weiß ich nicht, wie man die tatsächlichen Werte in einer Abfrage überprüft, um dies zu überprüfen. Ich kann nur die items.toString () - Methode verwenden, um das generierte SQL auszugeben, das Platzhalter enthält.

Ich habe es versucht: 1. db.Log = Console.Out; , das aufgrund eines Fehlers nicht kompiliert wurde, dass "db.Log" nicht definiert wurde (auch die automatische Vervollständigung schlug nicht "Log" vor). Wohingegen db von DbContext abgeleitet ist. 2. Wenn auch "Objekte" in ObjectQuery umgewandelt werden und dann .ToTraceString () nicht funktioniert, stürzt das Programm zur Laufzeit mit der Fehlermeldung ab, dass die Umwandlung ungültig ist.

Wenn das wichtig ist: Ich benutze .NET 4.0 und EntityFramework.5.0.0.

Fragen

  1. Wie wird die vollständige SQL (einschließlich der Werte von Platzhaltern) protokolliert / ausgegeben?
  2. Wie behebt man dieses Problem auf elegante Weise? ... ich meine nicht einen Hack, der nur eine Sekunde von der 'Zeit' subtrahiert, die in inValidate ()! /
  3. "ValidTo" zugewiesen ist

Mit freundlichen Grüßen

Stefan

BEARBEITEN (mehr Details gefunden)

Ich habe überprüft, was mit dem SQL-Profiler passiert, was gut zu sein scheint. Zeitstempel mit hohen (siebenstelligen) Genauigkeiten werden bei der Abfrage korrekt geliefert. ABER: Ich bekomme das SELECT nicht das falsche Ergebnis. Also ich vermutete: es muss etwas Caching sein. Also habe ich ein db.SaveChanges(); direkt vor meine LINQ Abfrage gestellt. Jetzt habe ich alle Abfragen im Profiler.

Ich habe den folgenden Code ausprobiert, um den Datentyp in der Datenbank zu ändern. Wie es von Slauma vorgeschlagen wurde (siehe Ссылка ).

%Vor%

Ich habe die gesamte Datenbank vor dem Neustart gelöscht ...

Ergebnis: Kein Erfolg mit HasPrecision (x); wo x einer von 0, 3 ist; (mit oder ohne db.SaveChanges () direkt davor); ABER: x = 7 funktioniert ziemlich gut mit db.SaveChanges (); direkt vor der Abfrage ...

Also, leider ist dieses Problem immer noch vorhanden ...

Aktueller Workaround

Ich wenden die folgende Methode auf einen beliebigen DateTime-Wert an, bevor Sie ihn einer Datenbankobjekteigenschaft zuweisen. Es rundet nur die DateTime auf volle Sekunden Genauigkeit (die ich in der DB konfiguriert). Dies gilt auch für eine DateTime, die für den Vergleich verwendet wird.

Ergebnis: Das ist mehr ein Hack als eine Lösung! Ich werde Zugriffsfunktionen für alle Setter-Methoden schreiben müssen, damit eine direkte Zuweisung nicht zufällig erfolgen kann.

%Vor%     
SDwarfs 23.10.2012, 15:43
quelle

1 Antwort

0

Frage 1 Wie wird das vollständige SQL (einschließlich der Werte von Platzhaltern) protokolliert? Ich denke, der beste Weg ist mit SQL Server Profiler. Es zeigt alle Aussagen und Werte. Oder Ссылка

Ich kenne keine andere Möglichkeit, die ausgeführten Befehle zu extrahieren.

    
Steven Spyrka 23.01.2013 13:59
quelle