Archive for February, 2014

Nagy SQL objektumok listázása

Wednesday, February 19th, 2014

Ha véletlenül nem menne az SSMS riportja:

SELECT
t.NAME AS TableName,
i.name as indexName,
sum(p.rows) as RowCounts,
sum(a.total_pages) as TotalPages,
sum(a.used_pages) as UsedPages,
sum(a.data_pages) as DataPages,
(sum(a.total_pages) * 8) / 1024 as TotalSpaceMB,
(sum(a.used_pages) * 8) / 1024 as UsedSpaceMB,
(sum(a.data_pages) * 8) / 1024 as DataSpaceMB
FROM
sys.tables t
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
WHERE
t.NAME NOT LIKE ‘dt%’ AND
i.OBJECT_ID > 255 AND
i.index_id <= 1 GROUP BY t.NAME, i.object_id, i.index_id, i.name ORDER BY TotalSpaceMB SELECT OBJECT_NAME(i.OBJECT_ID) AS TableName, i.name AS IndexName, i.index_id AS IndexID, 8 * SUM(a.used_pages) AS 'Indexsize(KB)' FROM sys.indexes AS i JOIN sys.partitions AS p ON p.OBJECT_ID = i.OBJECT_ID AND p.index_id = i.index_id JOIN sys.allocation_units AS a ON a.container_id = p.partition_id GROUP BY i.OBJECT_ID, i.index_id, i.name ORDER BY 'Indexsize(KB)' desc [/source]

Rétegek közötti kommunikáció

Monday, February 10th, 2014

Tegyük fel emailt akarok küldeni egy weboldalról, amiben linkekeket kell elhelyezni, amik hivatkoznak a weboldal urljeire.
Az email generálás a business logic jellegű komponensekben van. Ezeknek nem illik kinyúlkálni HttpContextekbe meg mindenféle webes cuccokba, mert ők nem webes cuccok. De ebben az esetben mégis csak fel kéne dinamikusan deríteni, hol fut a webapp, mert urleket kell generálni.

Ha kézzel passzolom át a szükséges infót, így néz ki a hívási lánc:

ArticleController.ArticleEdit => (innentől BBL, nem web) IArticleManager.UpdateArticle => INotificationManager.ArticleModified => INotificationFormatter.SendNotification

Na, a NotificationFormatternek már tudni kell urleket gyártani, a felette futó website intrinsic property-jei alapján.
Ezt kézzel átpasszolni a teljes láncon ronda. Mi jöhet még szóba? Statikus változók, amit a webapp indulásakor pl. a global.asaxben feltöltök, és a BLL-ben kiolvasom? Nem tetszik, de egyszerű. Utálom a statikusokat, szétborítanak minden tesztet.
Létrehozni egy IWebEnvironment interfészt, amit a tesztekben fake-elek, élőben pedig szintén a web indulásakor betárazok a DI containerbe? Kicsit körmönfont, de ez egy fokkal jobban tetszik.
Ötlet?

SQL Server Full text index probléma és megoldás

Monday, February 10th, 2014

Az egyik cégnek írtam full text keresős kódot. Az egész elég egyszerű stuff, full text catalogot kell létrehozni, és megjelölni az indexelendő oszlopokat. A catalog lehet accent sensitive vagy nem (ékezet számít-e), de mindig case insensitive (kis-nagy betű nem számít). A táblák oszlopainál meg kell adni egy word breakert, ez tördeli fel a szöveget szavakra, ezt indexeli, ebben keresünk.
A keresést az sql where feltételben contains és társai kulcsszavakkal lehet elérni. Én a containstable-t szoktam használni, mert így hatékonyan lehet limitálni a visszaadott halmazt, részletekbe most nem megyek bele.
Sokan nem tudják, de a bináris tartalomban is lehet keresni. Ehhez meg kell adni egy plusz oszlopot, amiben a tartalom file extensionjét kell megadni. Ez alapján kikeresi a registryben a megfelelő IFilter (ez még com) implementációt, ami kiszedi neki a szavakat a bináris moslékból. Van pl. pdfhez, htmlhez, office doksikhoz, képekhez (állítólag ocrezik, nekem még nem működött), stb. Szóval hatékonyan lehet kerestetni nagy doksikban is.
A probléma esetünkben az volt, hogy C#-ra adott vissza eredményeket, c#-ra nem. Ez ezért fura, mert a case sensitivity-t nem is lehet állítani, alapban nem az.
Már elkezdtem írni az ms fórumra, amikor a precíz dokumentálás érdekében elkezdtem bepasztázni a DDLeket:

CREATE FULLTEXT CATALOG [xxx] WITH ACCENT_SENSITIVITY = OFF;
CREATE FULLTEXT INDEX ON [KB].[Article](
[ArticleText] LANGUAGE [English], 
[ArticleTitle] LANGUAGE [English])
KEY INDEX [PK_Article] ON ([xxx], FILEGROUP [PRIMARY])
WITH (CHANGE_TRACKING = AUTO, STOPLIST = SYSTEM);

Na, hol a hiba?
Rossz volt a word breaker! Véletlenül angolt állítottam be. Ezzel már egyszer szívtam, akkor az ékezetes keresés volt beteg, főleg a híres őű betűink miatt.
Mi a helyes, ha magyar szöveget indexelünk? Hungarian sajnos nincs. Szlovák van, román van, ukrán van. Magyar nincs. Mi marad nekünk? Neutral. Mi ilyen langyi nemzet vagyunk, ilyen semlegesek, a mi karaktereink mellett csak ezzel lehet rendesen kerestetni. Persze, ragozást, szótőkeresést ne várjunk így el, ami a többi nyelvben rendesen van implementálva.
De örüljünk annak, ami van, neutral beállítás mellett már mindkét szí sárpot megtalálja.
Hogy angol mellett miért nem? Nem tudom.

Service locator pattern design kérdés

Monday, February 3rd, 2014

Sokak szerint Service Locator pattern antipattern.
Ok, ha egy ezer soros osztályban (ez már önmagában code smell) tucatnyi metódusban el vannak dugva service locator hívások, akkor a kódot olvasva nehéz meghatározni, milyen függőségei vannak, így nehéz tesztelni is (tudjuk, a kódot embereknek írjuk, nem a compilernek, az megérti a dzsuvát is). Ebben a helyzetben a konstruktor injectionnel nyilvánvalóan be lehet küldeni a függőségeket, az osztály elejét elolvasta azonnal szembeötlik, miket kell kifakelni, ha tesztelni akarjuk.
Na, de mi van a facade vagy controller jellegű osztályokkal? Ezek sok tucatnyi más osztállyal működnek együtt, pont ez a feladatuk, hogy a külvilágnak ne kelljen a belső részleteteket megérteni. Az ilyen osztályoknak tucatnyi függősége van, amelyeket viszont -szerintem- értelmetlen lenne konstrukciós időben létrehozni, főleg, ha jelentős részét nem is fogják használni a közeljövőben. Ilyenkor tudomásom szerint nem nagyon marad más, mint hogy a hívott metódusokban service locatorral létrehozni a függőséget, és belehívni.
Mindezt csak azért vetem fel, mert rossz érzésem van, amikor leírom egy kódban, hogy Di.Resolve(), de az előbbi érvelés alapján meg tudom indokolni, mikor mégis csak jogos a service locator.
Csak én csinálok ebből lelkiismereti kérdést?