Domanda

Sto scrivendo un C # di routine per chiamare un proc memorizzato. Nella lista dei parametri che sto passando, è possibile che uno dei valori possono essere legalmente nullo. Così ho pensato di utilizzare una linea come questa:

cmd.Parameters.Add(new SqlParameter("@theParam", theParam ?? DBNull.Value));

Purtroppo, questo restituisce il seguente errore:

  

CS0019: Operatore '??' non può essere applicato a operandi di tipo 'stringa' e 'System.DBNull'

Ora, questo sembra abbastanza chiaro, ma non capisco la logica dietro di esso. Perché questo non funziona? (E spesso, quando non capisco il motivo per cui qualcosa non funziona, non è che non può il lavoro ... è che io sto facendo male.)

Devo veramente di allungare questo fuori in un più istruzione if-then?

Modifica (Per inciso, a coloro che suggerisce di utilizzare solo "null" così com'è, non funziona ho inizialmente pensato che nulla sarebbe auto-tradotto in DBNull troppo, ma a quanto pare. non lo fa. (Chi lo sapeva?))

È stato utile?

Soluzione

Non come questo, no. I tipi devono corrispondere. Lo stesso vale per il ternario.

Ora, da "match", non significa che devono essere gli stessi. Ma essi devono essere compatibili assegnazione. In sostanza:. Nello stesso albero di ereditarietà

Un modo per aggirare il problema è quello di lanciare la stringa di opporsi:

var result = (object)stringVar ?? DBNull.Value;

Ma non mi piace questo, perché significa che stai contando più sul costruttore SqlParameter per ottenere i tipi di destra. Invece, mi piace fare in questo modo:

cmd.Parameters.Add("@theParam", SqlDbTypes.VarChar, 50).Value = theParam;
// ... assign other parameters as well, don't worry about nulls yet

// all parameters assigned: check for any nulls
foreach (var p in cmd.Parameters) 
{ 
    if (p.Value == null) p.Value = DBNull.Value; 
}

Si noti anche che ho dichiarato in modo esplicito il tipo di parametro.

Altri suggerimenti

new SqlParameter("@theParam", (object)theParam ?? DBNull.Value)

Il ?? operatore restituisce l'operando di sinistra, se non è nullo, altrimenti la funzione restituisce l'operando a destra. Ma nel tuo caso sono diversi tipi, in modo che non funziona.

L'operatore Null Coalesce solo con i dati dello stesso tipo. Non è possibile inviare NULL al SqlParamater come questo farà Sql Server dice che non è stato specificato il parametro.

È possibile utilizzare

new SqlParameter("@theParam", (object)theParam ?? (object)DBNull.Value)

In alternativa è possibile creare una funzione che restituiscono DBNull quando viene trovato nulla, come

public static object GetDataValue(object o)
{
    if (o == null || String.Empty.Equals(o))
        return DBNull.Value;
    else
        return o;
}

E poi chiamare

new SqlParameter("@theParam", GetDataValue(theParam))

Il motivo non è possibile utilizzare l'operatore nulla si fondono è che deve restituire un tipo e si stanno fornendo più di un tipo. theParam è una stringa. DbNull.Value è un riferimento a un'istanza statica di tipo System.DBNull . Questo è ciò che la sua attuazione assomiglia;

public static readonly DBNull Value = new DBNull(); 
//the instantiation is actually in the 
//static constructor but that isn't important for this example

Quindi, se si dovesse avere un metodo NullCoalesce, quale sarebbe il suo tipo di ritorno sarà? Non può essere sia System.String e System.DBNull, deve essere uno o l'altro, o un tipo genitore comune.

Quindi, che porta a questo tipo di codice;

cmd.Parameters.Add(
    new SqlParameter("@theParam", (object)theParam ?? (object)DBNull.Value)
);

Nel vostro proc memorizzato quando si dichiara la variabile in entrata, l'ha impostato la var uguale a null e quindi non si passa in dal codice csharp, sarà poi prendere il valore di default da SQL

@theParam as varchar(50) = null

e poi nel vostro csharp

if (theParam != null)
    cmd.Parameters.Add(new SqlParameter("@theParam", theParam));

Questo è come io di solito passare l'opzione e / o valori di default ai miei stored procedure

Sono abbastanza sicuro che solo di passaggio un null per i risultati SqlParameter costruttore in esso viene inviato come un DBNull.Value ... potrei sbagliarmi, dato che io uso le EnterpriseLibraries per l'accesso DB, ma sono abbastanza sicuro che l'invio di un nulla va bene lì.

cmd.Parameters.Add (new SqlParameter ( "@ theParam", (theParam == null) DBNull.Value:? TheParam));

Utilizzare questa sintassi:

(theParam come oggetto) ?? (DBNull.Value come oggetto)

In questo caso le due parti del operatore ?? sono dello stesso tipo.

Non è sicuro che la risposta alla tua domanda specifica, ma come su questo?

string.IsNullOrEmpty(theParam) ? DBNull.Value : theParam

o se vuoto è ok

(theParam == null) ? DBNull.Value : theParam
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top