sql >> Database teknologi >  >> RDS >> Sqlserver

Hvad er den bedste metode til at overføre parametre til SQLCommand?

Hvad foregår der derinde?

Du citerer parameterlisterne for adskillige overbelastninger af Add . Dette er bekvemmelighedsmetoder, der svarer direkte til konstruktøroverbelastninger for SqlParameter klasse. De konstruerer i det væsentlige parameterobjektet ved at bruge en hvilken som helst konstruktør, der har samme signatur som den bekvemmelighedsmetode, du kaldte, og kalder derefter SqlParameterCollection.Add(SqlParameter) sådan her:

SqlParameter foo = new SqlParameter(parameterName, dbType, size);
this.Add(foo);

AddWithValue ligner, men tager bekvemmeligheden endnu længere og indstiller også værdien. Det blev dog faktisk indført for at løse en rammefejl. For at citere MSDN,

Overbelastningen af ​​Add der tager astring, og et objekt blev forældet på grund af mulig tvetydighed medSqlParameterCollection.Add overbelastning, der tager en String og en SqlDbType enumerationsværdi, hvor overføring af et heltal med strengen kunne fortolkes som værende enten parameterværdien eller den tilsvarendeSqlDbType værdi. Brug AddWithValue hver gang du vil tilføje en parameter ved at angive dens navn og værdi.

Konstruktøren overbelaster for SqlParameter klasse er blot bekvemmeligheder til at indstille instansegenskaber. De forkorter koden med marginal indvirkning på ydeevnen:konstruktøren kan omgå seter-metoder og operere direkte på private medlemmer. Hvis der er en forskel, vil det ikke være meget.

Hvad skal jeg gøre?

Bemærk følgende (fra MSDN)

For tovejs- og outputparametre og returværdier skal du indstille værdien Size . Dette er ikke påkrævet for inputparametre, og hvis det ikke udtrykkeligt er angivet, udledes værdien af ​​den faktiske størrelse af den angivne parameter, når en parametriseret sætning udføres.

Standardtypen er input. Men hvis du tillader, at størrelsen kan udledes på denne måde, og du genbruger parameterobjektet i en løkke (du sagde, at du var bekymret for ydeevne), så vil størrelsen blive sat af den første værdi, og eventuelle efterfølgende værdier, der er længere, vil blive klippet. Dette er naturligvis kun signifikant for værdier med variabel længde, såsom strenge.

Hvis du sender den samme logiske parameter gentagne gange i en løkke, anbefaler jeg, at du opretter et SqlParameter-objekt uden for løkken og størrelser det passende. Overdimensionering af en varchar er harmløs, så hvis det er en PITA for at få det nøjagtige maksimum, skal du bare sætte den større, end du nogensinde forventer, at kolonnen skal være. Fordi du genbruger objektet i stedet for at oprette en ny for hver iteration, vil hukommelsesforbruget i løbet af løkken sandsynligvis falde også selvom man bliver en smule spændt på overstørrelsen.

Sandt at sige, medmindre du behandler tusindvis af opkald, vil intet af dette gøre den store forskel. AddWithValue opretter et nyt objekt og undgår størrelsesproblemet. Det er kort og godt og let at forstå. Hvis du går gennem tusindvis, så brug min tilgang. Hvis du ikke gør det, skal du bruge AddWithValue for at holde din kode enkel og nem at vedligeholde.

2008 var længe siden

I årene siden jeg skrev dette, har verden ændret sig. Der er nye former for date, og der er også et problem, der ikke faldt mig ind, før et nyligt problem med datoer fik mig til at tænke over konsekvenserne af udvidelsen.

Udvidelse og indsnævring, for dem, der ikke er bekendt med vilkårene, er kvaliteter ved datatypekonverteringer. Hvis du tildeler en int til en double, er der intet tab af præcision, fordi double er "bredere". Det er altid sikkert at gøre dette, så konvertering er automatisk. Dette er grunden til, at du kan tildele en int til en double, men hvis du går den anden vej, skal du lave en eksplicit cast - double to int er en indsnævrende konvertering med potentielt tab af præcision.

Dette kan gælde for strenge:NVARCHAR er bredere end VARCHAR, så du kan tildele en VARCHAR til en NVARCHAR, men at gå den anden vej kræver et cast. Sammenligning virker, fordi VARCHAR implicit udvides til NVARCHAR, men dette vil forstyrre brugen af ​​indekser!

C#-strenge er Unicode, så AddWithValue producerer en NVARCHAR-parameter. I den anden ende udvides VARCHAR-kolonneværdierne til NVARCHAR til sammenligning. Dette stopper ikke udførelse af forespørgsler, men det forhindrer indekser i at blive brugt. Det er dårligt.

Hvad kan du gøre ved det? Du har to mulige løsninger.

  • Skriv eksplicit parameteren. Dette betyder ikke mere AddWithValue
  • Skift alle strengkolonnetyper til NVARCHAR.

Ditching VARCHAR er nok den bedste idé. Det er en simpel ændring med forudsigelige konsekvenser, og det forbedrer din lokaliseringshistorie. Du har dog muligvis ikke dette som en mulighed.

I disse dage laver jeg ikke meget direkte ADO.NET. Linq2Sql er nu mit foretrukne våben, og det at skrive denne opdatering har fået mig til at undre mig over, hvordan den håndterer dette problem. Jeg får et pludseligt brændende ønske om at tjekke min dataadgangskode for opslag via VARCHAR-kolonner.

2019 og verden er gået videre igen

Linq2Sql er ikke tilgængelig i dotnet Core, så jeg bruger Dapper. [N]VARCHAR-problemet er stadig en ting, men det er ikke længere så langt begravet. Jeg tror på, at man også kan bruge ADO, så tingene er gået rundt i den forbindelse.



  1. Sådan rettes Microsoft SQL Server Error 926? - Løst

  2. Problemer med at åbne MDF-fil, fordi den siger SQL-fejl 5171? - Et gæsteindlæg af Andre Williams

  3. PDO MySQL:Brug PDO::ATTR_EMULATE_PREPARES eller ej?

  4. MySQL - kan jeg begrænse den maksimalt tilladte tid for en forespørgsel at køre?