Author Archives: Robert Haken

avatar Neznámé

About Robert Haken

Software Architect, Founder at HAVIT, Microsoft MVP - ASP.NET/IIS

ASP.NET WebForm Page Lifecycle Diagram (Léon Andianarivony)

Viz též můj podrobný diagram včetně request fází.

image

TRUNCATE TABLE vs. DELETE

Příkaz TRUNCATE TABLE vyprázdní tabulku a má tak efekt podobný příkazu DELETE (bez omezujících podmínek). Ve skutečnosti je však jejich funkce dosti odlišná.

TRUNCATE TABLE je ale rychlejší, používá méně systémových prostředků a méně prostředků transakčního logu, než DELETE (neloguje mazání každé jednotlivé řádky).

TRUNCATE TABLE navíc vyresetuje identity counter na počáteční hodnotu!!!

TRUNCATE TABLE neaktivuje TRIGGER !!!

DELETE vymaže řádky po jednom a do transaction-logu se zaznamená každé jednotlivé vymazání samostatně. Naproti tomu TRUNCATE TABLE vymaže data dealokací (uvolněním) datových stránek (data pages) použitých pro tabulku a do transaction-logu jsou zaznamenány jen tyto dealokace.

Exchange neodesílá, snaží se doručovat na divné IP adresy

Symptom

Pozoruhodné chování Exchange 2003 serveru. Neodchází maily do věšiny domén, zbytek zůstává ve frontě. Po bližším ohledání je v eventech vidět, že Exchange na některé pokusy vyhodí chybu, že mu protější strana neodpovídá. Z některých eventů je poznat, že komunikuje s podivnými IP adresami protější domény, které neodpovídají MX záznamům, ale jiným adresám v cílové doméně (nejpíš hlavní adresy domény, blíže jsem neprozkoumal).

Do domén, kde se adresa SMTP serveru náhodou shoduje s takto určenou IP adresou Exchange serveru, tak tam jsou maily doručeny v pohodě.

Příčina

Toto podivuhodné chování se projevilo na stroji Windows 2003 Server R2, který neměl na síťovém rozhraní nastaven DNS server. DNS služba však na něm běžela (to však nemusí být podstatné).

Každopádně stačilo nastavit DNS sám na sebe a vše se hned rozjelo. Čím resolvoval doposud, těžko říct. Očekával bych, že nebude resolvovat vůbec, ale nějak resolvoval…

Uložení výsledku stored procedury pomocí SELECT INTO

Když neznáme přesnou strukturu výsledku stored procedury, nemůžeme použít CREATE TABLE a INSERT … EXEC. Dá se to obejít pomocí OPENQUERY:

exec sp_serveroption [SERVER_NAME] , 'data access', 'true'

SELECT * INTO #W FROM OPENQUERY([SERVER_NAME], 'exec sp_who')
SELECT * FROM #W

SQL: Doplňování (padding) čísel nulami zleva na pevný počet míst (15 -> 00015)

Možná to jde lépe, ale co třeba takto:

= REPLACE(STR(15, 5, 0), ' ', '0')

Funkce STR(num, length, decimals) převede číslo na řetězec určené délky (doplněný zleva mezerami) a s daným počtem desetinných míst.

Nebo takto?

= RIGHT('00000' + cislo, 5)

Většinou si formátování řešíme až v prezentační vrstvě, ale někdy se to může hodit…

SQL: Určení věku osoby z data narození

Vypadá to jako triviální problém, nicméně triviální řešení zde nejsou správná.

Nejprve tedy správné řešení:

/*
   Vrátí věk ke vztažnému datu určený dle data narození.
*/
ALTER FUNCTION dbo.Age 
(
   @DatumNarozeni smalldatetime,
   @VztazneDatum smalldatetime
)
RETURNS tinyint
AS
BEGIN
   RETURN DATEDIFF(year, @DatumNarozeni, @VztazneDatum)
      - (CASE WHEN (100 * MONTH(@VztazneDatum) + DAY(@VztazneDatum)) < (100 * MONTH(@DatumNarozeni) + DAY(@DatumNarozeni))
              THEN 1 ELSE 0 END)
END

A pár ukázek špatných řešení:

DATEDIFF(year, @birthdate, @enddate)

SELECT DATEDIFF (year, @birthdate, @endDate)
  - CASE WHEN DATEPART(dy, @birthdate) <= DATEPART(dy, @endDate) THEN 1 ELSE 0 END

První pokus od sebe jen odečte letošní letopočet od letopočtu narození.
Druhý pokus zase nefunguje korektně s přestupnými roky, protože pak není počet dnů od 1.1. stejný.

Cannot resolve collation conflict for UNION operation.

Zajímavá hříčka, která může klidně skončit chybou „Cannot resolve collation conflict for UNION operation.“

SELECT * FROM RealTable INTO #temp WHERE ...

SELECT * FROM #temp
UNION
SELECT * FROM RealTable 

Dejme tomu, že RealTable používá default database collation.
Přestože výše uvedené vypadá, že přeci nemůže být s COLLATION problém, může být.
#temptable se totiž vytváří v databázi tempdb, která může mít jiné collation, než naše user-databáze!!! …a problém je na světě.

DirectoryNotFoundException: Could not find a part of the path „C:\“.

Takovoudle prima výjimku dostaneme, pokud voláme System.IO.Directory.CreateDirectory(String path) a nemáme přístupová práva alespoň na prohlížení všech nadřazených složek, typicky třeba chceme-li vytvořit novou složku z webové aplikace.

Directory.CreateDirectory() totiž neslouží jen pro založení jedné složky, ale pokud je potřeba, vytvoří celou požadovanou cestu, založí všechny potřebné složky. Základní potíž je v tom, že si nekontroluje existenci složek zdola, ale shora. Takže požadavek na založení složky C:\Inetpub\wwwroot\WebApplication\slozka\ kontroluje nejprve existenci C:\, pak C:\Inetpub\, pak C:\Inetpub\wwwroot\. No a pokud nemáme práva alespoň LIST na celou trasu, tak jsme v loji…

HttpContext.Current.Cache vs. HttpRuntime.Cache

Jaký je rozdíl mezi HttpContext.Current.Cache oproti HttpRuntime.Cache?

Zdá se to být jednoduché, HttpContext.Cache dělá

public Cache get_Cache()
{
      return HttpRuntime.Cache;
}

Proč tedy používat HttpContext.Current.Cache?
Není důvod!!! Správné použití je HttpRuntime.Cache !!!
Když pomineme režii na vyhodnocení HttpContext.Current, tak je tu ještě jeden zcela zásadní důvod, proč používat HttpRuntime.Cache. Ten totiž funguje i v nových threadech, kde je HttpContext.Current null. A nejenom to, funguje dokonce i mimo webové aplikace, třeba v konzolovce.

Viz též