2012-11-19 4 views
55

Ho il seguente codice per specificare i parametri per la query SQL. Sto ottenendo seguente eccezione quando uso Code 1; ma funziona bene quando uso Code 2. In Code 2 abbiamo un controllo per null e quindi un blocco if..else.Eccezione quando il parametro AddWithValue è NULL

Eccezione:

La query con parametri '(nvarchar @application_ex_id (4000)) SELECT E.application_ex_id A' si aspetta che il parametro '@application_ex_id', che non è stato fornito.

Codice 1:

command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 

Codice 2:

if (logSearch.LogID != null) 
{ 
     command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
} 
else 
{ 
     command.Parameters.AddWithValue("@application_ex_id", DBNull.Value); 
} 

DOMANDA

  1. Puoi spiegare perché non è in grado di prendere NULL dal valore logSearch.LogID nel Codice 1 (ma in grado di accettare DBNull)?

  2. C'è un codice migliore per gestire questo?

Riferimento:

  1. Assign null to a SqlParameter
  2. Datatype returned varies based on data in table
  3. Conversion error from database smallint into C# nullable int
  4. What is the point of DBNull?

CODICE

public Collection<Log> GetLogs(LogSearch logSearch) 
    { 
     Collection<Log> logs = new Collection<Log>(); 

     using (SqlConnection connection = new SqlConnection(connectionString)) 
     { 
      connection.Open(); 

      string commandText = @"SELECT * 
       FROM Application_Ex E 
       WHERE (E.application_ex_id = @application_ex_id OR @application_ex_id IS NULL)"; 

      using (SqlCommand command = new SqlCommand(commandText, connection)) 
      { 
       command.CommandType = System.Data.CommandType.Text; 

       //Parameter value setting 
       //command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
       if (logSearch.LogID != null) 
       { 
        command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
       } 
       else 
       { 
        command.Parameters.AddWithValue("@application_ex_id", DBNull.Value); 
       } 

       using (SqlDataReader reader = command.ExecuteReader()) 
       { 
        if (reader.HasRows) 
        { 
         Collection<Object> entityList = new Collection<Object>(); 
         entityList.Add(new Log()); 

         ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader); 

         for (int i = 0; i < records.Count; i++) 
         { 
          Log log = new Log(); 
          Dictionary<string, object> currentRecord = (Dictionary<string, object>)records[i]; 
          EntityDataMappingHelper.FillEntityFromRecord(log, currentRecord); 
          logs.Add(log); 
         } 
        } 

        //reader.Close(); 
       } 
      } 
     } 

     return logs; 
    } 
+3

Che cosa si intende per proiettile meglio? Il codice 2 è il modo corretto per inviare un valore nullo a un database. –

+0

Riferimento: http://stackoverflow.com/questions/13265704/conversion-error-from-database-smallint-into-c-sharp-nullable-int – Lijo

risposta

84

Fastidioso, non è vero?

È possibile utilizzare:

command.Parameters.AddWithValue("@application_ex_id", 
     ((object)logSearch.LogID) ?? DBNull.Value); 

Oppure, in alternativa, utilizzare uno strumento come "Dapper", che farà tutto ciò che pasticciano per voi.

Ad esempio:

var data = conn.Query<SomeType>(commandText, 
     new { application_ex_id = logSearch.LogID }).ToList(); 

Sono tentati per aggiungere un metodo per dapper per ottenere il IDataReader ... non proprio ancora sicuro se si tratta di una buona idea.

+0

@Phil infatti; molte cose possono ... ma non mi piace aggiungere metodi di estensione su 'object', e non possiamo vedere se sia' Nullable 'vs' stringa', ecc ... ma sì: potrebbe essere fatto facilmente abbastanza. –

+1

Stavo pensando un'estensione sulla proprietà 'Parameters' - è un' Object'? –

+3

@Phil hmmm, sì è, e vedo cosa intendi ... forse 'AddWithValueAndTreatNullTheRightDamnedWay (...)' –

1

qualche problema, ha permesso con Necessariamente set SQLDbType

command.Parameters.Add("@Name", SqlDbType.NVarChar); 
command.Parameters.Value=DBNull.Value 

dove SqlDbType.NVarChar si digita. Necessariamente impostare il tipo SQL. Enjou

34

trovo più facile basta scrivere un metodo di estensione per il SqlParameterCollection che gestisce i valori nulli:

public static SqlParameter AddWithNullableValue(
    this SqlParameterCollection collection, 
    string parameterName, 
    object value) 
{ 
    if(value == null) 
     return collection.AddWithValue(parameterName, DBNull.Value); 
    else 
     return collection.AddWithValue(parameterName, value); 
} 

Poi basta chiamare in:

sqlCommand.Parameters.AddWithNullableValue(key, value); 
+0

_valore_ può essere ** int o int ?, stringa, bool o bool ?, DateTime o Datetime? **, etc? – Kiquenet

+0

@Kiquenet Sì ... – AxiomaticNexus

+2

Ho letto la risposta di Marc e ho pensato "Penso che preferirei semplicemente scrivere un metodo di estensione per la collezione Parameters", quindi ho fatto scorrere un pelo ... (il bello di un metodo di estensione è che Posso fare una singola ricerca/sostituzione dopo e tutti i miei aggiornamenti del codice sono fatti) – jleach

2

Solo nel caso in cui si' facendo ciò mentre si chiama una stored procedure: penso che sia più facile da leggere se si dichiara un valore predefinito sul parametro e lo si aggiunge solo quando necessario.

Ad esempio: (SQL)

DECLARE PROCEDURE myprocedure 
    @myparameter [int] = NULL 
AS BEGIN 

(C#)

int? myvalue = initMyValue(); 
if (myvalue.hasValue) cmd.Parameters.AddWithValue("myparamater", myvalue); 

So che questo è vecchio, ma trovo questa utile e ha voluto condividere.

-3

Creare una classe statica come questo:

public static class Extensions 
{ 
    public static string RemoveNulls(this string container) 
    { 
     if (container == null) 
      container = ""; 
     return container; 
    } 
} 

Poi nel codice, fare questo:

Parameters.AddWithValue(sName, Value.RemoveNulls()); 

Questa è la prova e molto facile da usare

+1

Questo inserirà "" e non null ... – Lars

+0

Questo è quello che vuole - non inserire un null – TheWizardOfTN