Hoe ga je om met Nullable type met SqlDataRecord

Ik ontleed xml (LINQ tot XML) en ik gebruik een nullable type ( int? en decimal? ) in gevallen waarin het element/attribuut leeg is. Echter, wanneer ik mijn verzameling bouw om door te geven aan de DB (Using TVP), weet ik niet hoe ik de gevallen moet behandelen waarin de waarde eigenlijk null is. Ik kan geen null in de SqlDataRecord SetInt32 of SetDecimal doorgeven en ik wil niet op nul instellen .... Ik wil eigenlijk dat het nul is.

Mij ​​geen overbelasting vertellen voor int ?

Teller hieronder is een null-type ( int? Count)

SqlDataRecord rec = new SqlDataRecord(
              new SqlMetaData("Name", SqlDbType.VarChar, 50),
              new SqlMetaData("Type", SqlDbType.VarChar, 50),
              new SqlMetaData("Count", SqlDbType.Int));

   rec.SetString(0, dm.Name);
   rec.SetString(1, dm.Type);
   rec.SetString(2, dm.Count);

Om het even welke ideeën hoe te om dit zonder nul te behandelen (het handhaven van nul)?

9

4 antwoord

Uitbreidingsmethode:

static class SqlDataRecordExtensions
{
    static void SetNullableInt32(this SqlDataRecord rec, int index, Int32? value)
    {
        if (value.HasValue)
            rec.SetInt32(index, value.GetValueOrDefault());
        else
            rec.SetDBNull(index);
    }
}

of, om SetSqlInt32 te gebruiken zoals gesuggereerd door D Stanley:

static class SqlDataRecordExtensions
{
    static void SetNullableInt32(this SqlDataRecord rec, int index, Int32? value)
    {
        rec.SetSqlInt32(index, value.HasValue ? value.GetValueOrDefault() : SqlInt32.Null);
       //                                     ^^^^^^^^^^^^^^^^^^^^^^^^^
       //                                     You can leave out the cast to (SqlInt32),
       //                                     because the conversion is implicit
    }
}

Opmerking, 9 december 2013: Terugkerende naar dit antwoord vanwege een opmerking, merkte ik een kleine kans op verbetering op, gebaseerd op de serie van Eric Lippert over niet-verplaatsbare micro-optimalisaties, die te vinden is op http://ericlippert.com/2012/12/20/nullable-micro-optimizations-part-one/ .

Kortom, terwijl de eigenschap Waarde minder hoeft te typen en daarom aantoonbaar meer optimaal is voor de programmeur, moet deze een uitzondering werpen als HasValue false is. Aan de andere kant is de GetValueOrDefault() -methode een eenvoudige veldtoegang. Vanwege dit, vereist GetValueOrDefault() minder instructies en is de kans groter dat deze inline is, dus is het meer optimaal voor de compiler en de processor.

12
toegevoegd
@RichardCollette Bedankt voor de reactie; Daar heb ik niet aan gedacht. Ik vermoed dat je gelijk hebt dat het prestatieverschil waarschijnlijk niet significant is voor de meeste toepassingen. Ik heb echter de neiging om sterkere typen op filosofische gronden te verkiezen. Uw commentaar inspireert mij ook om een ​​kleine optimalisatie toe te voegen waar ik twee jaar geleden nog niet aan had gedacht.
toegevoegd de auteur phoog, de bron
@PhilCooper Wat is SetDBNull in versie 4? Welke 'B'-zaak?
toegevoegd de auteur phoog, de bron
@PhilCooper Aha, zie ik. Toen je 'B'-geval zei, dacht ik dat je bedoelde dat er verschillende gevallen waren en dat een van hen was geïdentificeerd met de letter' B '. Zo verward. Ik heb het antwoord gecorrigeerd; bedankt voor het wijzen op de fout.
toegevoegd de auteur phoog, de bron
Niet zeker of het framework is gewijzigd, maar het is SetDBNull in versie 4 (let op het geval 'B').
toegevoegd de auteur Phil Cooper, de bron
@phoog SetDbNull is SetDBNull zie hier: SqlDataRecord.SetDBNull
toegevoegd de auteur Phil Cooper, de bron
@phoog geen probleem, graag helpen.
toegevoegd de auteur Phil Cooper, de bron
+1, erg leuk ..
toegevoegd de auteur Jeff Ogata, de bron
SetValue (ordinal, object) verwerkt null-waarden en null-waarden met een beetje overhead voor het controleren van type- en waardelengte. Het prestatieverschil is mogelijk niet merkbaar.
toegevoegd de auteur Richard Collette, de bron

Ik heb nog nooit met SqlDataRecord gewerkt, maar bij het gebruik van DataTable en DataRow , of bij het gebruik van geparametriseerde query's, geef ik null met behulp van DBNull.Value .

Met SqlDataRecord ziet het ernaar uit dat u de SetDBNull methode.

3
toegevoegd

Moet SetSqlInt32 gebruiken in plaats van SetString . Proberen

rec.SetSqlInt32(2, (dm.Count.HasValue ? new SqlInt32(dm.Count) : SqlInt32.Null) );
0
toegevoegd
Dat zou moeten zijn rec.SetSqlInt32 (2, (dm.Count.HasValue? New SqlInt32 (dm.Count.Value): SqlInt32.Null));
toegevoegd de auteur phoog, de bron
Verder, zoals ik me realiseerde bij het bewerken van mijn antwoord, betekent de impliciete conversie van int naar SqlInt32 dat je dit kunt doen: rec.SetSqlInt32 (2, dm.Count.HasValue? Dm.Count.Value: SqlInt32.Null);
toegevoegd de auteur phoog, de bron

//Ive vond dit om het beste voor mij te werken bij het controleren of omgaan met nullable types   // in mijn voorbeeld controleer ik waarden die zijn opgeslagen in een reeks String []

sqlcmdUpdateRecord.Parameters.AddWithValue("@strSomeValue", (strRecord[(int) 
DataFields.SomeDataField] as object) ?? DBNull.Value);
0
toegevoegd