Optimalni řešení funkcí a tříd   zodpovězená otázka

VB.NET, Architektura, Optimalizace, Databáze

Zdravím všechny.

Mám takový dotaz, který se ani tak netýká funkčnosti, ale spíše vhodného navržení struktury tříd a funkcí. Chtěl bych znát váš názor případně připomínky. Uvedu příklad.

Mám nějaký soubor tříd, který pracuje s aplikací SQL server. Jde většinou o volání různých uložených procedur. Každou uloženou proceduru volám pomocí konkrétní funkce nebo procedury ve VB.NET.

V tuto chvíli každé funkci (proceduře) v .NET předávám kromě potřebných parametrů (parametrů pro uloženou proceduru) i konekt string. A tady se nabízí dotaz, zda je to dobré řešení. Zda není např. lepší funkcím předávat rovnou objekt SQLConnection. Nebo ani SQLConnection ani konekt string vůbec funkcím nepředávat, ale ponechat jeho vytváření, inicializaci, použítí a následné uzavření na každé jednotlivé funkci.

Funkce používám pro klasickou desktopovou aplikaci pro Windows.

Co si myslíte, že je vhodnější z hlediska optimalizace kódu? Případně víte o nějakém dobrém informačním zdroji, kde bych mohl o této problematice něco načerpat?

Díky moc.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Toto se řeší pomocí datového kontextu a případně datové bázové třídy.

Tedy:

- máte třídu, která se chová jako tzv. datový kontext - její vytvoření je možné například pomocí connection stringu, měla by zajistit otevření spojení a poskytnutí připojení (pomocí nějaké vlastnosti nebo funkce) - tím zajístíme jednu formu předávání připojení do databáze, která lze případně změnit, či rozšířit na jednou místě

- datové třídy budou dědit z nějaké bázové abstraktní třídy - ta implementuje například vlastnost, která dokáže držet objekt typu právě datového kontextu - tím zajistíme, že každá datová třída má univerzálního předka, kterým definujeme připojení k databázi pomocí datového kontextu - ve výsledku pak metoda v potomcích při volání uložených procedur využije objektu datového kontextu, ze kterého si jednotným způsobem získá připojení

- při používání datových tříd pak před voláním jednotlivých metod nastavíme unifikovaným způsobem vlastnost datového kontextu

Ve výsledku zajistíme tyto unifikované součásti:

- definice připojení k databázi a jeho vytváření obstarává třída datového kontextu (na jednom místě)

- nastavování datového kontextu do datovýh tříd se provádí nastavením jednotné vlastnosti v datových třídách (pocházející z bázové třídy - tedy jednoho místa)

- používání bázové třídy datové třídy je ve všech datových třídách stejné - případné rozšiřování se týká pouze bázové třídy nebo datového kontextu - tak jako tak se řeší vše na jednom místě a velmi elegantním způsobem

Snad to pomůže :-)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Děkuji Vám moc za odpověď.

Myslíte, že by bylo možné uvést nějaký základní a jednoduchý příklad takovéto implementace? Postačí pouze základní konstrukce, případně existuje někde nějaký vzorový příklad jak na to?

Mnohokrát Vám děkuji.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ok, ale kód který tu budu uvádět není kompletní, chybí tam ošetření problémů s otevíráním spojení atp. Na to ale přijdete při testování.

Ze základu tu mám třídu datového kontextu. Té se předá připojovací řetězec při inicializaci a následně lze z vlastnosti Pripojeni získat spojení do databáze:


Public Class DatovyKontext
    Public Sub New(ByVal pripojovaciRetezec As String)
        Pripojeni = New Data.SqlClient.SqlConnection(pripojovaciRetezec)
        Pripojeni.Open()
    End Sub

    Private pripojeni_ As Data.SqlClient.SqlConnection

    Public Property Pripojeni() As Data.SqlClient.SqlConnection
        Get
            Return pripojeni_
        End Get
        Set(ByVal value As Data.SqlClient.SqlConnection)
            pripojeni_ = value
        End Set
    End Property
End Class

Dále tu máme základní bázovou třídu pro datové třídy. Nedělá nic jiného, než že schraňuje v proměnné kontext pro své potomky právě třídu datového kontextu (tím pádem ji vůbec nezajímá co v kontextu je, jen uchovává jeho instanci):

Public MustInherit Class DatovaBazovaTrida
    Public Sub New(ByVal kontext As DatovyKontext)
        Me.kontext = kontext
    End Sub

    Protected kontext As DatovyKontext
End Class

Teď následuje ukázka jak bázovou třídu a její odkaz na kontext používat v své nové datové třídě (dědí z bázové třídy a při komunikace s databází používá připojení z kontextu poskytnutého právě bázovou třídou):

Public Class MojeDatovaTrida1
    Inherits DatovaBazovaTrida

    Public Sub New(ByVal kontext As DatovyKontext)
        MyBase.New(kontext)
    End Sub

    Public Sub ZavolejDatabazi()
        Dim prikaz = kontext.Pripojeni.CreateCommand()
        prikaz.CommandText = "exec sp_MojeUlozenaProcedura"
        prikaz.ExecuteNonQuery()
    End Sub
End Class

Nyní už následuje jen příklad použití. Kód nejprve vytvoří datový kontext (připojení k databázi), pak vytvoří instanci datové třídy, které předá připojení uschované v datovém kontextu a nakonec na inicializované datové třídě zavolá požadovaný příkaz:

Module Module1

    Sub Main()
        Dim kontext = New DatovyKontext("Server=.\SQLEXPRESS;Database=Test1;uid=login;pwd=heslo;")

        Dim datovaTrida = New MojeDatovaTrida1(kontext)

        datovaTrida.ZavolejDatabazi()
    End Sub

End Module

Uff, to jsem se rozepsal :-). Je to popsané trochu stručně, ale snad se skrz to prokoušete. Pokud ne, ptejte se. Toto řešení se používá velmi často, je hodně obecné a elegantní. Například lze využívat jeden datový kontext pro více tříd, je možné do datového kontextu implementovat transakce atp. atp....

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Mockrát Vám děkuji. Tohle určitě bude stačit. Ještě jednou díky za Vaši ochotu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pane Jecha,

ještě jednou Vám moc děkuji. Ušetřil jste mi zjevně mnoho práce a Vámi uváděné řešení skutečně funguje. Jak elegantní! Jdu přepsat mé stávající řešení.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback