Die parametrisierte Abfrage… erwartet den Parameter '@units', der nicht angegeben wurde

74

Ich bekomme diese Ausnahme:

Die parametrisierte Abfrage '(@Name nvarchar (8), @ type nvarchar (8), @ unit nvarchar (4000), @ rang' erwartet den Parameter '@units', der nicht angegeben wurde.

Mein Code zum Einfügen lautet:

public int insertType(string name, string type, string units = "N\\A", string range = "N\\A", string scale = "N\\A", string description = "N\\A", Guid guid = new Guid())
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        SqlCommand command = new SqlCommand();
        command.CommandText = "INSERT INTO Type(name, type, units, range, scale, description, guid) OUTPUT INSERTED.ID VALUES (@Name, @type, @units, @range, @scale, @description, @guid) ";
        command.Connection = connection;
        command.Parameters.AddWithValue("@Name", name);
        command.Parameters.AddWithValue("@type", type);
        command.Parameters.AddWithValue("@units", units);
        command.Parameters.AddWithValue("@range", range);
        command.Parameters.AddWithValue("@scale", scale);
        command.Parameters.AddWithValue("@description", description);
        command.Parameters.AddWithValue("@guid", guid);
        return (int)command.ExecuteScalar();
    }
}

Die Ausnahme war eine Überraschung, da ich die AddWithValueFunktion verwende und sicherstelle, dass ich Standardparameter für die Funktion hinzugefügt habe.

Gelöst:

Das Problem war, dass einige Parameter leere Zeichenfolgen enthielten (die die Standardeinstellung überschreiben).

Dies ist der Arbeitscode:

public int insertType(string name, string type, string units = "N\\A", string range = "N\\A", string scale = "N\\A", string description = "N\\A", Guid guid = new Guid())
    {
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
            SqlCommand command = new SqlCommand();
            command.CommandText = "INSERT INTO Type(name, type, units, range, scale, description, guid) OUTPUT INSERTED.ID VALUES (@Name, @type, @units, @range, @scale, @description, @guid) ";
            command.Connection = connection;
            command.Parameters.AddWithValue("@Name", name);
            command.Parameters.AddWithValue("@type", type);

            if (String.IsNullOrEmpty(units))
            {
                command.Parameters.AddWithValue("@units", DBNull.Value); 
            }
            else
                command.Parameters.AddWithValue("@units", units);
            if (String.IsNullOrEmpty(range))
            {
                command.Parameters.AddWithValue("@range", DBNull.Value);
            }
            else
                command.Parameters.AddWithValue("@range", range);
            if (String.IsNullOrEmpty(scale))
            {
                command.Parameters.AddWithValue("@scale", DBNull.Value);
            }
            else
                command.Parameters.AddWithValue("@scale", scale);
            if (String.IsNullOrEmpty(description))
            {
                command.Parameters.AddWithValue("@description", DBNull.Value);
            }
            else
                command.Parameters.AddWithValue("@description", description);




            command.Parameters.AddWithValue("@guid", guid);


            return (int)command.ExecuteScalar();
        }


    }
Yogevnn
quelle
1
Sie haben vergessen, das @als erstes Zeichen für jeden Parameternamen anzugeben.
Andrew Morton
@AndrewMorton: Warum beschwert sich die Fehlermeldung @unitseher als die @Name, die zuerst erscheint?
ODER Mapper
@ORMapper Ich nehme an, es muss nicht in der Reihenfolge gesucht werden, in der sie geliefert werden.
Andrew Morton
Ich bin schockiert, weil immer noch niemand diese Frage beantwortet hat. Übrigens, 2Upvotes?
Soner Gönül
@ AndrewMorton Ich habe die @ und immer noch die gleiche Ausnahme hinzugefügt
Yogevnn

Antworten:

98

Versuchen Sie diesen Code:

SqlParameter unitsParam = command.Parameters.AddWithValue("@units", units);
if (units == null)
{
    unitsParam.Value = DBNull.Value;
}

Und Sie müssen alle anderen Parameter auf Nullwerte überprüfen. Wenn es null ist, müssen Sie den DBNull.ValueWert übergeben.

Denis
quelle
1
Ich glaube nicht, dass es null sein könnte, weil OP den Parameter wie string units = "N\\A"
folgt
3
Es könnte, weil Sie Methode wie diese aufrufen könneninsertType(null, null, null, null, null, null);
Denis
Problem gelöst! Ich werde meine Nachricht mit Lösung bearbeiten. Danke euch allen!
Yogevnn
@GrantWinney Anscheinend funktioniert das nicht so. Der Parameter muss im aufrufenden Code weggelassen und nicht auf gesetzt werden null. Benannte und optionale Argumente
Andrew Morton
@GrantWinney Standardwerte funktionieren so nicht. Sie gelten nur, wenn Sie nichts übergeben (wenn Sie das Argument ganz weglassen). Wenn Sie überhaupt etwas nullpassieren, ist es das, was der Angerufene sieht.
35

Hier ist eine Möglichkeit, den Null-Koaleszenz-Operator zu verwenden:

cmd.Parameters.AddWithValue("@units", units ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@range", range ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@scale", scale ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@description", description ?? (object)DBNull.Value);

Oder für eine strengere Typprüfung:

cmd.Parameters.Add("@units", SqlDbType.Int).Value = units ?? (object)DBNull.Value;
cmd.Parameters.Add("@range", SqlDbType.Int).Value = range ?? (object)DBNull.Value;
cmd.Parameters.Add("@scale", SqlDbType.Int).Value = scale ?? (object)DBNull.Value;
cmd.Parameters.Add("@description", SqlDbType.VarChar).Value = description ?? (object)DBNull.Value;

Der Bediener muss auch verkettet sein:

int?[] a = { null, null, 1 };
Console.WriteLine(a[0] ?? a[1] ?? a[2]);
Wille
quelle
3

Diese Erweiterungsklasse war mir bisher ein paar Mal nützlich für folgende Probleme:

public static class DbValueExtensions
{
    // Used to convert values coming from the db
    public static T As<T>(this object source)
    {
        return source == null || source == DBNull.Value
            ? default(T)
            : (T)source;
    }

    // Used to convert values going to the db
    public static object AsDbValue(this object source)
    {
        return source ?? DBNull.Value;
    }
}

Sie würden es normalerweise in zwei Szenarien verwenden. Erstens, wenn Sie Parameter für Ihre Abfrage erstellen:

var parameters = new Dictionary<string, object>
{
    { "@username", username.AsDbValue() },
    { "@password", password.AsDbValue() },
    { "@birthDate", birthDate.AsDbValue() },
};

oder beim Parsen der SqlReader-Werte:

while (reader.Read())
{
    yield return new UserInfo(
        reader["username"].As<string>(),
        reader["birthDate"].As<DateTime>(),
        reader["graduationDate"].As<DateTime?>(),
        reader["nickname"].As<string>()
    );
}
Mladen B.
quelle
1
command.Parameters.AddWithValue("@Name", (name == null ? "" : name));
سعد الضبي
quelle
0

Dies ist eine Methode, die mit mehreren Parametern wiederverwendet werden kann:

public void NullorEmptyParameter(QC.SqlCommand command, string at, string value)
{
    if (String.IsNullOrEmpty(value))
    {
        command.Parameters.AddWithValue(at, DBNull.Value);
    }
    else
        command.Parameters.AddWithValue(at, value);
}

Und dann können Sie es für so viele Befehle und Parameter wiederverwenden:

NullorEmptyParameter(command, "@Idea_ID", Idea_ID);
NullorEmptyParameter(command, "@Opportunities_or_Idea", Opportunities_or_Idea);
locnguyen
quelle