it-swarm.com.de

Formatfehler bei Verwendung von DateTime in einem SqlParameter für gespeicherte Prozedur

Ich versuche, eine gespeicherte Prozedur (auf einem SQL 2005-Server) in C #, .NET 2.0, mit DateTime als Wert für SqlParameter aufzurufen. Der SQL-Typ in der gespeicherten Prozedur ist "datetime".

Das Ausführen des Sprocs über SQL Management Studio funktioniert einwandfrei. Aber bei jedem Aufruf von C # erhalte ich eine Fehlermeldung zum Datumsformat.

Wenn ich SQL Profiler ausführe, um die Aufrufe zu überwachen, kopiere ich und füge den Aufruf exec ein, um zu sehen, was los ist. Dies sind meine Beobachtungen und Notizen zu dem, was ich versucht habe:

1) Wenn ich das DateTime direkt als DateTime übergebe oder in SqlDateTime konvertiere, ist das Feld von einem PAIR aus einfachen Anführungszeichen umgeben, wie z

@Date_Of_Birth=N''1/8/2009 8:06:17 PM''

2) Wenn ich DateTime als String übergebe, erhalte ich nur die einfachen Anführungszeichen

3) Die Verwendung von SqlDateTime.ToSqlString() führt nicht zu einer UTC-formatierten Datums-/Uhrzeitzeichenfolge (auch nach der Konvertierung in die Weltzeit).

4) Die Verwendung von DateTime.ToString() führt nicht zu einer UTC-formatierten Datum/Uhrzeit-Zeichenfolge.

5) Durch manuelles Setzen von DbType für SqlParameter auf DateTime werden die obigen Beobachtungen nicht geändert.

Meine Fragen sind also: Wie um alles in der Welt kann ich C # dazu bringen, die richtig formatierte Zeit in SqlParameter zu überschreiten? Sicherlich ist dies ein häufiger Anwendungsfall. Warum ist es so schwierig, mit der Arbeit zu beginnen? Ich kann DateTime scheinbar nicht in eine SQL-kompatible Zeichenfolge konvertieren (z. B. '2009-01-08T08: 22: 45')

EDIT

RE: BFree, der Code zum Ausführen des Sprocs lautet wie folgt:

using (SqlCommand sprocCommand = new SqlCommand(sprocName))
{
    sprocCommand.Connection = transaction.Connection;
    sprocCommand.Transaction = transaction;
    sprocCommand.CommandType = System.Data.CommandType.StoredProcedure;
    sprocCommand.Parameters.AddRange(parameters.ToArray());
    sprocCommand.ExecuteNonQuery();
}

Um genauer zu gehen, was ich versucht habe:

parameters.Add(new SqlParameter("@Date_Of_Birth", DOB));

parameters.Add(new SqlParameter("@Date_Of_Birth", DOB.ToUniversalTime()));

parameters.Add(new SqlParameter("@Date_Of_Birth", 
    DOB.ToUniversalTime().ToString()));

SqlParameter param = new SqlParameter("@Date_Of_Birth", 
    System.Data.SqlDbType.DateTime);
param.Value = DOB.ToUniversalTime();
parameters.Add(param);

SqlParameter param = new SqlParameter("@Date_Of_Birth", 
    SqlDbType.DateTime);
param.Value = new SqlDateTime(DOB.ToUniversalTime());
parameters.Add(param);

parameters.Add(new SqlParameter("@Date_Of_Birth", 
    new SqlDateTime(DOB.ToUniversalTime()).ToSqlString()));

Additional EDIT

Die, von der ich dachte, dass sie am wahrscheinlichsten funktioniert:

SqlParameter param = new SqlParameter("@Date_Of_Birth",  
    System.Data.SqlDbType.DateTime);
param.Value = DOB;

Ergibt diesen Wert im exec-Aufruf, wie er im SQL Profiler angezeigt wird

@Date_Of_Birth=''2009-01-08 15:08:21:813''

Wenn ich das so ändere:

@Date_Of_Birth='2009-01-08T15:08:21'

Es funktioniert, aber es wird nicht mit einfachen Anführungszeichen analysiert und es wird nicht korrekt in ein DateTime mit dem Abstand zwischen Datum und Uhrzeit und mit den Millisekunden am Ende konvertiert.

pdate und Erfolg

Ich hatte den obigen Code nach der Aufforderung von unten kopiert/eingefügt. Ich habe die Dinge hier und da so zurechtgeschnitten, dass sie prägnant sind. Es stellte sich heraus, dass mein Problem in dem Code lag, den ich ausgelassen hatte. Ich bin mir sicher, dass jeder von Ihnen es gleich bemerkt hätte. Ich hatte meine Sproc-Anrufe in eine Transaktion eingebunden. Es stellt sich heraus, dass ich einfach nicht transaction.Commit() gemacht habe !!!!! Ich schäme mich, das zu sagen, aber da hast du es.

Ich weiß immer noch nicht, was mit der vom Profiler zurückgegebenen Syntax los ist. Ein Mitarbeiter hat mit seiner eigenen Instanz des Profilers von seinem Computer aus zugesehen und die korrekte Syntax zurückgegeben. Beim Betrachten der gleichen Ausführungen von meinem Profiler wurde die falsche Syntax angezeigt. Es fungierte als Red Herring und ließ mich glauben, dass es ein Problem mit der Abfragesyntax gab, anstatt der viel einfacheren und zutreffenderen Antwort, die ich brauchte, um die Transaktion zu bestätigen!

Ich habe eine Antwort unten als richtig markiert und einige positive Stimmen für andere abgegeben, weil sie die Frage schließlich beantwortet haben, auch wenn sie mein spezifisches Problem (Gehirnversagen) nicht behoben haben.

22
Matt

Wie richten Sie das SqlParameter ein? Sie sollten die Eigenschaft SqlDbType auf SqlDbType.DateTime und dann das DateTime direkt an den Parameter übergeben (NICHT in eine Zeichenfolge konvertieren, dann fragen Sie nach einer Reihe von Problemen).

Sie sollten in der Lage sein, den Wert in den DB zu bekommen. Wenn nicht, ist hier ein sehr einfaches Beispiel, wie es gemacht wird:

static void Main(string[] args)
{
    // Create the connection.
    using (SqlConnection connection = new SqlConnection(@"Data Source=..."))
    {
        // Open the connection.
        connection.Open();

        // Create the command.
        using (SqlCommand command = new SqlCommand("xsp_Test", connection))
        {
            // Set the command type.
            command.CommandType = System.Data.CommandType.StoredProcedure;

            // Add the parameter.
            SqlParameter parameter = command.Parameters.Add("@dt",
                System.Data.SqlDbType.DateTime);

            // Set the value.
            parameter.Value = DateTime.Now;

            // Make the call.
            command.ExecuteNonQuery();
        }
    }
}

Ich denke, ein Teil des Problems hier ist, dass Sie besorgt sind, dass die Tatsache, dass die Zeit in UTC ist, nicht an SQL Server übermittelt wird. Zu diesem Zweck sollten Sie dies nicht tun, da SQL Server nicht weiß, dass sich eine bestimmte Zeit in einem bestimmten Gebietsschema/einer bestimmten Zeitzone befindet.

Wenn Sie den UTC-Wert speichern möchten, konvertieren Sie ihn in UTC, bevor Sie ihn an SQL Server übergeben (es sei denn, Ihr Server hat dieselbe Zeitzone wie der Clientcode, der den DateTime generiert, und selbst dann ist dies ein Risiko. IMO). SQL Server speichert diesen Wert und wenn Sie ihn zurückerhalten, müssen Sie ihn selbst anzeigen, wenn Sie ihn in Ortszeit anzeigen möchten (was mit der DateTime -Struktur problemlos möglich ist).

Wenn Sie die Konvertierung durchführen und dann das konvertierte UTC-Datum (das Datum, das durch Aufrufen der ToUniversalTime -Methode und nicht durch Konvertieren in einen String) an das übergeben gespeicherte Prozedur.

Wenn Sie den Wert zurückerhalten, rufen Sie die ToLocalTime -Methode auf, um die Zeit in der lokalen Zeitzone abzurufen.

29
casperOne

So füge ich Parameter hinzu:

sprocCommand.Parameters.Add(New SqlParameter("@Date_Of_Birth",Data.SqlDbType.DateTime))
sprocCommand.Parameters("@Date_Of_Birth").Value = DOB

Ich gehe davon aus, dass es beim Ausschreiben von DOB keine Anführungszeichen gibt.

Verwenden Sie ein Steuerelement eines Drittanbieters, um das Datum abzurufen? Ich hatte Probleme mit der Art und Weise, wie der Textwert aus einigen von ihnen generiert wird.

Funktioniert es schließlich, wenn Sie das Attribut .Value des Parameters eingeben, ohne auf DOB zu verweisen?

3
K Richard

Wenn du benutzt Microsoft.ApplicationBlocks.Data es wird Ihre Sprocs eine einzelne Zeile aufrufen

SqlHelper.ExecuteNonQuery(ConnectionString, "SprocName", DOB)

Oh, und ich denke, casperOne ist richtig ... Wenn Sie die richtige Datums- und Uhrzeiteinstellung für mehrere Zeitzonen sicherstellen möchten, konvertieren Sie einfach den Wert in UTC, bevor Sie den Wert an SQL Server senden

SqlHelper.ExecuteNonQuery(ConnectionString, "SprocName", DOB.ToUniversalTime())
0

Benutz einfach:

 param.AddWithValue("@Date_Of_Birth",DOB);

Das wird sich um all Ihre Probleme kümmern.

0
BFree