26. 11. 2017, Vladimír Klaus, navštíveno 1612x

ASP.NET/C#

A je to tu zase. Několik let funguje nějaký kód bez nejmenších problémů a když ho je trochu upravíte, tak začne vykazovat zcela nesmyslnou chybu. Měl jsem jednoduchou proměnnou, kterou jsem pak připojil k hlavnímu dotazu.

var HledaciPodminka = " WHERE NeniAktualni='False'";

Po čase jsem potřeboval přidat další podmínku:

var HledaciPodminka = " WHERE NeniAktualni='False' AND BU='" + App.BU + "' ";

Co je App.BU? To je docela jedno, ale typ je to "dynamic". Díky tomu se i HledaciPodminka stala "dynamic". Na tom asi není, resp. nemělo by být nic fatálního. Ovšem, když pak toto zavoláte, tak to není dobré...

var selectQueryString = "SELECT TOP 300 * FROM SHIPMENTShipments "
  + HledaciPodminka;
var data = db.Query(selectQueryString);
var PocetPolozek = data.Count();

Prostě to skončí chybou:

Je to docela šílené, protože co jiného, než string byste měli předávat jako parametr Query. Bohužel díky "dynamic" na začátku je vše následující také "dynamic" a tak i data jsou "dynamic" a u nich nelze volat metodu Count(), ale jen se ptát na vlastnost Count.

Řešení je naštěstí zcela jednouché - všude, kde máte var a dává to smysl, nahraďte za string. V tu chvíli se i proměnná data změní z dynamic na IEnumerable<dynamic> a vše bude fungovat tak jako dřív.

Problém pokračuje

V předchozím příkladu jsme sice převedli "selectQueryString" na string, ale co když chcete dotaz používat opravdu korektně, tedy s parametry?

string selectQueryString = "SELECT TOP 300 * FROM SHIPMENTShipments WHERE BU=@0";
var data = db.Query(selectQueryString, App.BU);
var PocetPolozek = data.Count();

To je opět průšvih, protože "selectQueryString" je sice string, ale dotaz je volán s parametrem, který je dynamic a jsme tam, kde jsme byli. Pak nezbývá než přímo data nadeklarovat jako IEnumerable<dynamic>, což už projde v pohodě...

string selectQueryString = "SELECT TOP 300 * FROM SHIPMENTShipments WHERE BU=@0";
IEnumerable<dynamic>data = db.Query(selectQueryString, App.BU);
var PocetPolozek = data.Count();

Ale je to otravné. Proto je nejlepší se dynamic dat úplně a co nejdříve zbavit a převést na reálný datový typ. V mém případě int. A je opravdu skvělé, že funkce TryParse() se s tím korektně vypořádá - je to sice dynamic, ale je to hlavně string, takže převod proběhne.

App.BU = "408";
int idBU = int.TryParse(App.BU, out idBU) ? idBU : 0;
var selectQueryString = "SELECT TOP 300 * FROM SHIPMENTShipments WHERE BU=@0";
var data = db.Query(selectQueryString, idBU);
var PocetPolozek = data.Count();

Viz též: