sql >> Databáze >  >> RDS >> Sqlserver

Jaký je nejlepší způsob předání parametrů SQLCommand?

Co se tam děje?

Uvádíte seznamy parametrů pro několik přetížení Add . Toto jsou pohodlné metody, které přímo odpovídají přetížení konstruktoru pro SqlParameter třída. V podstatě zkonstruují objekt parametru pomocí jakéhokoli konstruktoru, který má stejný podpis jako metoda pohodlí, kterou jste zavolali, a poté zavolají SqlParameterCollection.Add(SqlParameter) takhle:

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

AddWithValue je podobný, ale posouvá pohodlí ještě dále a také nastavení hodnoty. Ve skutečnosti však byl zaveden, aby vyřešil rámcovou chybu. Chcete-li citovat MSDN,

Přetížení Add který používá astring a objekt byl zastaralý z důvodu možné nejednoznačnosti s SqlParameterCollection.Add přetížení, které vyžaduje String a SqlDbType hodnota výčtu, kde by předávání celého čísla s řetězcem mohlo být interpretováno jako hodnota parametru nebo odpovídajícíSqlDbType hodnota. Použijte AddWithValue kdykoli chcete přidat parametr zadáním jeho názvu a hodnoty.

Konstruktor se přetíží pro SqlParameter třídy jsou pouhými vymoženostmi pro nastavení vlastností instance. Zkracují kód s marginálním dopadem na výkon:konstruktor může obejít metody setter a pracovat přímo se soukromými členy. Pokud existuje rozdíl, nebude velký.

Co mám dělat?

Všimněte si následujícího (z MSDN)

Pro obousměrné a výstupní parametry a návratové hodnoty musíte nastavit hodnotu Size . Toto není vyžadováno pro vstupní parametry, a pokud není explicitně nastaveno, je hodnota odvozena ze skutečné velikosti zadaného parametru při provádění parametrizovaného příkazu.

Výchozí typ je input. Pokud však dovolíte, aby velikost byla odvozena takto a objekt parametru recyklujete ve smyčce (říkali jste, že vám jde o výkon), pak bude velikost nastavena první hodnotou a všechny následující hodnoty, které jsou delší, budou oříznuté. To je samozřejmě významné pouze pro hodnoty s proměnnou délkou, jako jsou řetězce.

Pokud opakovaně předáváte stejný logický parametr ve smyčce, doporučuji vytvořit objekt SqlParameter mimo smyčku a vhodně jej upravit. Nadměrná velikost varcharu je neškodná, takže pokud je to PITA, abyste získali přesné maximum, nastavte jej větší, než byste kdy očekávali, že bude sloupec. Protože objekt recyklujete, místo abyste pro každou iteraci vytvořili nový, pravděpodobně poklesne spotřeba paměti po dobu trvání cyklu i když vás to předimenzování trochu vzruší.

Po pravdě řečeno, pokud nezpracujete tisíce hovorů, nic z toho příliš nezmění. AddWithValue vytvoří nový objekt, čímž se vyhne problému velikosti. Je to krátké a sladké a snadno pochopitelné. Pokud procházíte tisíci, použijte můj přístup. Pokud ne, použijte AddWithValue aby byl váš kód jednoduchý a snadno udržovatelný.

Rok 2008 byl hodně dávno

Za ta léta, co jsem to napsal, se svět změnil. Existují nové druhy dat a je tu také problém, který mě nenapadl, dokud mě nedávný problém s daty nepřiměl přemýšlet o důsledcích rozšíření.

Rozšiřování a zužování, pro ty, kteří tyto pojmy neznají, jsou vlastnosti převodů datových typů. Pokud přiřadíte int k double, nedojde ke ztrátě přesnosti, protože double je "širší". Je to vždy bezpečné, takže převod je automatický. To je důvod, proč můžete přiřadit int k double, ale opačným způsobem musíte provést explicitní obsazení - double to int je zužující převod s potenciální ztrátou přesnosti.

To se může týkat řetězců:NVARCHAR je širší než VARCHAR, takže můžete přiřadit VARCHAR k NVARCHAR, ale jít opačným způsobem vyžaduje přetypování. Porovnání funguje, protože VARCHAR se implicitně rozšiřuje na NVARCHAR, ale to bude narušovat použití indexů!

Řetězce C# jsou Unicode, takže AddWithValue vytvoří parametr NVARCHAR. Na druhém konci se hodnoty sloupce VARCHAR pro srovnání rozšíří na NVARCHAR. Tím se nezastaví provádění dotazu, ale zabrání se použití indexů. To je špatné.

co s tím můžete dělat? Máte dvě možná řešení.

  • Explicitně zadejte parametr. To znamená, že už žádné AddWithValue
  • Změňte všechny typy sloupců řetězců na NVARCHAR.

Vykopání VARCHAR je pravděpodobně nejlepší nápad. Je to jednoduchá změna s předvídatelnými důsledky a vylepšuje váš příběh o lokalizaci. Tuto možnost však možná nemáte.

V dnešní době moc přímo ADO.NET nedělám. Linq2Sql je nyní mou oblíbenou zbraní a psaní této aktualizace mě nechalo přemýšlet, jak tento problém řeší. Mám náhlou, spalující touhu zkontrolovat svůj přístupový kód k datům pro vyhledání pomocí sloupců VARCHAR.

2019 a svět se pohnul opět

Linq2Sql není k dispozici v dotnet Core, takže jsem zjistil, že používám Dapper. Problém [N]VARCHAR je stále věc, ale už není tak daleko. Věřím, že lze také použít ADO, takže se věci v tomto ohledu uzavřely.



  1. Jak zkompilovat všechny neplatné balíčky ve schématu?

  2. Seznam všech funkcí v databázi Oracle

  3. Testování příkazů DML pro OLTP v paměti

  4. Sloupce data v SQL-Serveru (MSSQL-JDBC 3.0) běžícím pod Java 1.7.0 byly načteny jako 2 dny v minulosti