Adatkezelés kategória bejegyzései

Szerdán SQL-es developer meetup

Ezen a héten szerdán ötödik állomásához érkezik a LogMeIn és a Microsoft Magyarország közös szervezésében készülő Enterprise Developer Meetup sorozat. Erre az alkalomra csupa adatbázisos témával készülünk, lesz szó teljesítményről, biztonságról és természetesen a felhőről is. Várunk mindenkit, akit érdekelnek a Microsoft adatbázis platformjának újdonságai, akár távolabbról architektúra szintjén, akár közelebbről, kód szinten.

kalen-delaney

Az első előadónk Kalen Delaney, aki 26 éve foglalkozik az SQL Serverrel, így nem véletlen, hogy az ő nevéhez kötődik szinte az összes “inside” és “internals” könyv a témában. Kalen kifejezetten a LogMeIn meghívására érkezik hazánkba, és szerdán az SQL Server 2014-ben bevezetett, korábban “Hekaton” kódnéven futó SQL Server In-Memory OLTP-ről fog beszélni. A Hekaton lényege, hogy az adatbázis motort az adatok memóriában történő tárolására optimalizálták, amivel természetesen jelentős teljesítmény növekedést lehet elérni.

 

koszo-karoly

Második előadónkat, Kószó Károlyt a magyar SQL fejlesztőknek nem kell bemutatni, hiszen 1996 és 2013 között a Microsoft Magyarország munkatársaként számos rendezvényen adott elő az SQL Serverről. Szerdán az SQL Server jogosultságkezeléséről fog beszélni, kitérve olyan kevésbé ismert témákra is, mint a tulajdonosi lánc és az aláírt tárolt eljárások. Érdemes elmélyednünk a témában, hiszen a legféltettebb adataink biztonságáról van szó!

 

 

 

dudas-viktor

Harmadik előadónk, Dudás Viktor, korábban már szerepelt nálunk, akkor az Azure Machine Learningről és gépi tanulásról beszélt. He is back! Ezúttal a Tabular Analysis Servert veszi górcső alá, természetesen a felhőben.

 

 

 

 

A társaság jó, a részvétel ingyenes, a szervezés érdekében csak annyit kérünk, nyomjatok egy RSVP: Yes-t előre.

Bővebb információ és jelentkezés itt:
http://www.meetup.com/Enterprise-Developer-Meetup/events/221592899/

Szeretettel várunk mindenkit szerdán 19 órakor a LogMeInben (Paulay Ede u. 12.)!

 

Technorati-címkék: ,,
Reklámok

Exception calling "SqlBackup" with "1" argument(s)

Az egyik szerverünkön az alábbi PowerShell script végzi az SQL Server adatbázisok mentését:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null

$server = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $dbInstance
$backup = New-Object ("Microsoft.SqlServer.Management.Smo.Backup")
$backup.Action = "Database"
$backup.BackupSetDescription = "Full backup of " + $dbName
$backup.BackupSetName = $dbName + " backup"
$backup.Database = $dbName
$backup.MediaDescription = "Disk"
$backup.Devices.AddDevice("$localSqlBackupPath", "File")
$backup.SqlBackup($server)

Ez a kód most már évek óta működik rendesen, szépen készülnek a backupok naponta. Ám az utóbbi időben érdekesen kezdett viselkedni a szkript: egyes adatbázisokat mindig lementett, másokat pedig – amikkel korábban nem volt gond – többnyire nem. A naplóba az alábbi hibaüzenet került:

Exception calling "SqlBackup" with "1" argument(s): 
"Backup failed for Server 'MyServer\MySqlInstance'. " At D:\Backups\BackupSite.ps1:151 char:22 + $backup.SqlBackup <<<< ($server) + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException

Nehezen derült ki, hogy a hibának semmi köze a függvény meghívásának módjához, hanem a problémát az okozza, hogy megnőtt az adatbázis, és az SqlBackup függvény 10 perc után timeoutolódik. A ServerConnection objektum StatementTimeout tulajdonságával lehet kikapcsolni az időtúllépés figyelését:

$server.ConnectionContext.StatementTimeout = 0

 

Technorati-címkék: ,

Amikor kell a régi Framework verzió az új mellé

Van egy alkalmazásunk, ami .NET Framework 4.0 Client Profile-t és SQL Server Compact Editiont használ, ClickOnce-szal települ, és ha szükséges, telepíti maga alá a Frameworköt is. Nincs benne semmi olyan, ami miatt ne futhatna régebbi Windowsokon, ami kell is, mert a felhasználóknál részben XP-k vannak. Az új verzió tesztelése közben szokás szerint felhúztam egy friss XP-s virtuális gépet, amire az alkalmazás új verziója sikeresen települt is, azonban az első adatbázis műveletnél az alábbi hibával elszállt:

System.DllNotFoundException: Unable to load DLL ‘sqlceme35.dll’: The specified module could not be found. (Exception from HRESULT: 0x8007007E)

A hivatkozott fájl természetesen ott volt a diszken, ahol a korábbi verziókban is, sőt a program új verziójába nem is kerültek olyan változások, amik ezt a hibát indokolták volna, ezért jogosan merült fel a kérdés, hogy mi változott?

A hiba nem jött elő sem Windows 8.1-en, sem Windows 7-en, sőt még azokon a régebben használt XP-s gépeken sem, amiken fent volt az alkalmazás korábbi verziója, és most csak frissítettük. És bár a korábbi verzió vígan futott XP-n, az új virtuális gépben ugyanolyan hibát produkált, mint az új verzió, így adódott a következtetés, hogy a virtuális gépben volt az eltérés.

Először a modern.ie oldalról letöltött virtuális gépet használtam, és arra gyanakodtam, hogy annak van valami specifikuma. Azután telepítettem egy saját virtuális gépet úgy, hogy az alap XP+SP3 telepítőre hosszú órák alatt keservesen felkínlódtam az összes Windows Update frissítést. A jelenség ugyanaz.

Végül ILSpy-jal belenéztem a programmal települő System.Data.SqlServerCe szerelvénybe, és mivel az még a .NET Framework 2.0 verziójára hivatkozott, próbaként feltelepítettem a régi Framework verziót. Csodák csodája a probléma megoldódott.

Az eset érdekességei:

  • A Windows Update nem telepítette a .NET Framework 2.0-át, csak az újabb verziókat. Ez régebben nem így volt.
  • A 4.0 Client Profile nem volt elég, mellé fel kellett telepíteni a 2.0 verziót.
  • Érthető, hogy Windows 7-en nem jött elő a hiba, hiszen ott az operációs rendszer része a .NET 2.0, de vajon miért ment simán 8.1-en, ahol alapból nincs feltéve a .NET 2.0?

 

Technorati-címkék:

Mi lesz veled SQL Server Compact Edition?

Aki próbálta már az SQL Server Compact Editiont, az tudja, hogy nagyon jó dolog. Persze nem mindenre, de amikor egy kicsi, beágyazható, Entity Frameworkkel elérhető SQL adatbázisra van szükség, akkor jó szolgálatot tesz. Hogy mennyire kicsi? Az x86 változata 1.72 MB, az x64 egy kicsit nagyobb, de az is mindössze 2.84 MB:

sqlce-files

Az ember a DLL-jeit odacsapja a projekthez és már megy is, nem kell telepíteni, nem kell hozzá admin jog, nem fut a háttérben service-ként stb. A 4.0 verzió már egészen megérett, működik a több felhasználós elérés, sőt az ASP.NET is támogatja.

Ehhez képest szomorúan tapasztaltam, hogy az SQL Server 2012 Management Studioban nem találtam a szokásos helyen:

sqlce-ssms

Ilyenkor az ember előveszi a Discontinued Management Tools Features in SQL Server 2012 doksit, ahol nyíltan ez áll:

“The SQL Server Compact Edition code editor has been removed from SQL Server Management Studio. Support for SQL Server Compact Edition has also been removed from Object Explorer, Solution Explorer, and Template Explorer. Use the Transact-SQL editors in Microsoft Visual Studio 2010 Service Pack 1 or Webmatrix instead.”

Sajnos a Visual Studioval sem jobb a helyzet, a Visual Studio 2013 Compatibility oldalon ezt olvashatjuk:

“Visual Studio 2013 doesn’t support SQL Server Compact Edition.”

Egyelőre nem tudom, hogy mi az SQL Compact roadmapje, de addig a következő lehetőségeket látom:

  • ErikEj blogjában számos okosság található az SQL Compacttal kapcsolatban, sőt ő készített egy SQL Server Compact Toolbox nevű bővítményt is, ami eddig is jó szolgálatot tett.
  • Lehetne használni LocalDB-t, de itt sem látok nagy mozgást, mióta az első verziója megjelent.
  • Át lehetne térni más adatbázis kezelőre. Ti mit használtok?

 

Meglepő kapcsolat bontások SQL Azure-ban

Gyakran lehet találkozni azzal a ténnyel, hogy mivel az SQL Azure ugyanazt a tabular data stream (TDS) protokollt támogatja, mint a teljes SQL Server, a programozási modell teljesen azonos a két esetben. Ebből viszont – a közhiedelemmel ellentétben – nem következik az, hogy az alkalmazásunk felhőbe költöztetése mindössze annyiból áll, hogy átállítjuk a connection stringet!

Az SQL Azure ugyanis számos olyan esetben is hajlamos bontani a kapcsolatot, amihez nem vagyunk hozzászokva a saját szervereinken. Íme két példa:

  • 40197 – The service has encountered an error processing your request. Please try again.
  • 40501 – The service is currently busy. Retry the request after 10 seconds.

Ennek az alapvető okai a hibatűrésben és a rendelkezésre állásban keresendőek. Ha a kérés kiszolgálásában részt vevő valamelyik szereplő hibás lesz vagy épp frissül, akkor a felhőnek köszönhetően nem lesz tartós leállásunk, de szolgáltatás visszaállásáig (ami rövid idő) a kapcsolatokat bontani fogja a szerver. A másik ok, hogy mivel az adatbázisok osztoznak bizonyos erőforrásokon, az SQL Azure query és connection throttling szolgáltatásai biztosítják, hogy egyik ügyfél se akaszthassa le teljesen a kiszolgálást. Ha túllépjük a limitet, hibát fogunk kapni.

Mindennek az az eredménye, hogy időnként elszállnak az adatbázis lekérdezéseink, de mivel ezek okai alapvetően átmeneti jelenségek, bátran megismételhetjük a lekérdezést kicsit később. Ez sajnos nagyon kellemetlen, mert általában arra számítva írjuk meg az adatelérési rétegünket, hogy ha az adatbázis nem elérhető, akkor nagy baj van, és nem szoktunk arra számítani, hogy a hiba másodperceken belül megszűnik magától.

Magyarul: SQL Azure-on futó alkalmazások esetén gondoskodnunk kell ezeknek a hibáknak a kezeléséről, és a hiba jellegétől függően meg kell ismételnünk a lekérdezést. Ha korábban nem volt az alkalmazásunkban ilyen intelligens retry-logika, akkor a felhőbe költöztetéskor ezt bele kell tennünk.

Néhány segítség:

 

Technorati-címkék: ,,,

Optimista konkurenciakezelés ASP.NET MVC-ben

Webes rendszerek esetén nem ritka, hogy ugyanahhoz az adathoz egyszerre több felhasználó fér hozzá és egyszerre módosítják azt. Ha nem teszünk semmit ellene, akkor a későbbi módosítás felülírja a korábbi módosítást, ami az esetek nagy részében nem egyezik a kívánatos eredménnyel. Alapvetően a következő lehetőségeink vannak:

  • Optimista konkurenciakezelés: nem zároljuk az adatot, mert bízunk abban, hogy nem lesz ütközés. Ha mégis előfordul, hogy két felhasználó egyszerre ugyanazt az adatot módosítja, akkor a második módosítás adatbázisba írása előtt figyelmeztetjük a felhasználót, hogy már elavult adatot módosít.
  • Pesszimista konkurenciakezelés: arra számítunk, hogy több felhasználó ugyanazt az adatot akarja módosítani, ezért amint az egyik felhasználó hozzáfér az adathoz zároljuk azt, és addig nem engedünk másik felhasználót hozzá, amíg az első módosítás be nem fejeződik.

Az optimista megoldás hátránya, hogy a felhasználó tipikusan későn értesül arról, hogy feleslegesen dolgozott, mégis sok adat és kevés felhasználó (például admin oldalak) esetén ez a célszerűbb megoldás, ugyanis nem kell zárakkal és azok feloldásával (pl. timeout) vesződnünk.

Az optimista megoldáshoz először is egy olyan mezőre van szükségünk az adatbázisban, ami a rekord módosításakor mindig frissül, azaz egy verzió vagy időbélyeg típusú mezőre. SQL Server esetén pont erre szolgál a timestamp típus, aminek a frissítéséről az SQL Server automatikusan gondoskodik. Tehát csak létre kell hoznunk az oszlopot, a többi megy magától:

VersionNumber timestamp NOT NULL

ORM használata esetén a modell frissítése után a VersionNumbernek byte[] típusú oszlopként kell megjelennie.

Ha egységesen akarunk eljárni és minden olyan táblában, ahol szükség van konkurenciakezelésre ugyanígy nevezzük az oszlopot, akkor célszerű kitalálnunk egy módszert, amivel hivatkozhatunk a “verziózott” táblákra. Ehhez készíthetünk öröklést az ORM modellben, vagy ha a Studio által generált modellt nem akarjuk bántani, akkor interfészt is bevezethetünk:

public interface IVersionedEntity
{
    byte[] VersionNumber { get; set; }
}

Az interfészt a partial osztályoknak köszönhetően külön fájlban alkalmazhatjuk a modellben lévő entitásokra, nem kell belenyúlni a modellbe. Például ha a modellünkben van egy Partner nevű osztály, akkor így “származtathatjuk” az interfészünkből:

public partial class Partner : IVersionedEntity
{
}

Ezzel készen vagyunk az adatbázissal és az adatelérési réteggel.

Következő lépésként fogjuk meg a dolgot a másik végéről, induljunk el a GUI irányából és okosítsuk fel a ViewModelt. Itt a módosítással kapcsolatos VM-ekbe kell tennünk egy VersionNumber tulajdonságot, amit a módosítás előtt feltöltünk az adatbázisból, és az update előtt összevetünk az adatbázisban tárolt értékkel. Itt is választhatjuk az interfészes megoldást, de ha spórolni akarunk a kóddal, akkor alkothatunk ősosztályt is:

public class VersionedObject
{
    [HiddenInput( DisplayValue = false )]
    public byte[] VersionNumber { get; set; }

    public string VersionNumberEncoded
    {
        get
        {
            return Convert.ToBase64String( this.VersionNumber );
        }
    }

}

A VersionNumberEncoded akkor lesz hasznos, ha az értéket például query stringben kell átadnunk, mert egyébként az MVC automatikusan gondoskodik a byte[] típusú érték Base64 kódolásáról, mielőtt a HiddenInput attribútum szerint kiírja egy rejtett mezőbe.

Ezek után a szerkesztéssel kapcsolatos viewmodeleket egyszerűen származtassuk ebből az ősosztályból:

public class EditPartnerVM : VersionedObject
{
    [HiddenInput(DisplayValue = false)]
    public int ID { get; set; }

    public string DisplayName { get; set; }
}

A modellbe így bekerült értékünket ne felejtsük el megutaztatni a kliensre:

@Html.EditorFor( m => m.VersionNumber )

Miután a böngészőből visszajön az adat, a mentés előtt össze kell vetnünk az adatbázisban lévő értékkel. Ehhez készíthetünk például egy CheckConcurrency( VersionedObject viewModel, IVersionedEntity entity ) függvényt, amely összehasonlítja a két paraméter VersionNumber tulajdonságát, és eltérés esetén kivételt dob. Én készítettem egy saját ObjectMissingException osztályt, amit akkor használok, ha az adatbázis rekord null (azaz már törölték a rekordot), és egy ObjectChangedException osztályt, amit akkor, ha a két verziószám eltér egymástól.

Természetesen a felhasználóval valahogy illik tudatnunk, hogy a művelet kudarcba fulladt. Ezt tehetjük például egy saját exception filterrel, ami ezeknél a kivételeknél egy hibaüzenetet tartalmazó view-t jelenít meg:

[AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, 
Inherited =
true, AllowMultiple = false )] public sealed class HandleConcurrencyErrorAttribute :
FilterAttribute, IExceptionFilter { public void OnException( ExceptionContext filterContext ) { if( filterContext.Exception.GetType() == typeof( ObjectChangedException ) ) { filterContext.ExceptionHandled = true; filterContext.Result = new ViewResult { ViewName = "_ObjectChanged" }; } if( filterContext.Exception.GetType() == typeof( ObjectMissingException ) ) { filterContext.ExceptionHandled = true; filterContext.Result = new ViewResult { ViewName = "_ObjectMissing" }; } } }

Legvégül ne felejtsük el ráaggatni ezt a filtert azokra az actionökre, amik a módosítás POST-ját kezelik, hogy a kivétel biztosan ne szálljon egészen a felhasználóig:

[HttpPost]
[HandleConcurrencyError]
public virtual ActionResult EditPartner( EditPartnerVM model )
{ ...

Ha kevés paraméterünk van (például Ajaxos hívások esetén), ne felejtsük el átadni a VersionNumberEncoded értékét az actionnek.

Ti hogyan oldjátok meg ezt a problémát?

 

Technorati-címkék: ,,

Meghalt a BIDS, éljen az SSDT BI!

Az SQL Server csapat tegnap bejelentette, hogy letölthető a Visual Studiohoz az a kiegészítés, aminek segítségével Reporting, Analysis és Integration Services projekteket készíthetünk a 2012-es verzióban.

ssdt-bi

A korábban Business Intelligence Development Studio néven futó csomag mostantól SQL Server Data Tools – Business Intelligence (SSDT BI) néven érhető el, és mindenféle upgrade/downgrade nélkül képes kezelni a VS 2010-ben készült projekteket, tehát immár nem szükséges csak emiatt telepítenünk a Studio korábbi verzióját.

A bejelentés: http://blogs.msdn.com/b/sqlrsteamblog/archive/2013/03/06/sql-server-data-tools-business-intelligence-for-visual-studio-2012-released-online.aspx

Letöltés (782 MB): http://www.microsoft.com/en-us/download/details.aspx?id=36843

 

Technorati-címkék: ,