Simple designs to solve enterprise problems - design and code to support multiple databases

The design intends to solve the following problems:

 

1. SQL Queries written in data access code is generally full with string concatenation which makes it difficult to read and un-maintainable as it grows

 

2. It gets even more difficult when your code supports multiple database server products and the queries are written in your data access code.

 

To solve these problems we need to do the following

 

1. Add a class called SQLHelper:

 

 

 

 

 

Imports System

Imports System.Collections

Imports System.Reflection

Imports System.Configuration

 

Friend Class SQLHelper

    Private Shared htQueries As Hashtable = New Hashtable

    Private Shared mExtension As String

 

    Private Const CURRENT_EXTENSION As String = “CURRENT_EXTENSION”

    Private Const DEFAULT_EXTENSION As String = “.sql.qry”

   

    Shared Sub New()

        If Not ConfigurationSettings.AppSettings.Item(CURRENT_EXTENSION) Is Nothing Then

            mExtension = ConfigurationSettings.AppSettings.Item(CURRENT_EXTENSION)

            Return

        End If

        mExtension = DEFAULT_EXTENSION

    End Sub

 

    Public Shared ReadOnly Property Extension() As String

        Get

            Return mExtension

        End Get

    End Property

 

    Public Shared Function GetQueryString(ByVal CurrentAssembly As [Assembly], ByVal FileName As String) As String

        Dim key As String = GetKey(CurrentAssembly, FileName)

        Return GetEmbeddedQuery(key)

    End Function

 

    Public Shared Function GetQueryString(ByVal FileName As String) As String

        Dim CurrentlyAssembly As [Assembly] = Reflection.Assembly.GetExecutingAssembly()

        Return GetQueryString(CurrentlyAssembly, FileName)

    End Function

 

    Public Shared Function GetQueryString(ByVal FileName As String, ByVal args() As String) As String

        Dim SQL As String = GetQueryString(FileName)

        Return String.Format(SQL, args)

    End Function

 

    Private Shared Function GetKey(ByVal CurrentAssembly As [Assembly], ByVal FileName As String) As String

        Dim TheNamespace As String = GetType(SQLHelper).Namespace

        If TheNamespace Is Nothing OrElse Trim(TheNamespace) = “” Then

            Return FileName

        Else

            Return TheNamespace & “.” & FileName

        End If

    End Function

 

    Public Shared Function GetEmbeddedQuery(ByVal FullPath As String) As String

        Dim CurrentlyAssembly As [Assembly] = Reflection.Assembly.GetExecutingAssembly()

        Return GetEmbeddedFileAsString(CurrentlyAssembly, FullPath)

    End Function

 

    Private Shared Function GetEmbeddedFileAsString(ByVal CurrentAssembly As [Assembly], ByVal key As String) As String

        SyncLock (htQueries)

            Dim SQL As String

            If htQueries.Item(key) Is Nothing Then

                Dim FullPath As String = key & mExtension

                SQL = GetEmbeddedResourceAsString(CurrentAssembly, FullPath)

                htQueries.Add(key, SQL)

            End If

        End SyncLock

        Return CType(htQueries.Item(key), String)

    End Function

 

    Public Shared Function GetEmbeddedResourceAsString(ByVal CurrentAssembly As [Assembly], ByVal FullPath As String) As String

        Dim ResultStream As System.IO.Stream = CurrentAssembly.GetManifestResourceStream(FullPath)

        If Not ResultStream Is Nothing Then

            Try

                Dim intStreamLen As Integer = CType(ResultStream.Length, Integer)

                Dim ByteArray(intStreamLen - 1) As Byte

                ResultStream.Read(ByteArray, 0, intStreamLen)

                Return System.Text.Encoding.UTF8.GetString(ByteArray)

            Catch e As Exception

                Throw New Exception(”Error reading resource”, e)

            Finally

                If Not ResultStream Is Nothing Then

                    ResultStream.Close()

                End If

            End Try

        Else

            Throw New Exception(”Resource not found”)

        End If

    End Function

 

End Class

 

 

The code written above contains the following:

1.    

mExtension: This member stores the default extension for the query files. The query files need to be stored in your data access project as embedded resources. You can keep multiple extensions for supporting multiple database products.
For ex. you have an extension “.sql.qry” for SQL Server/T-SQL “.ora.qry” for Oracle/PL-SQL

 

2.    

htQueries: This member is used to cache string from a query file once it is retrieved. This will prevent your code from calling expensive reflection code for retrieving each and every query.

 

3.    

GetQueryString(FileName as string): This is a method which takes the query file name as a parameter, retrieves the file from the assembly, reads the string and returns the query.

 

4.    

GetQueryString(FileName as string, args() as string): This method is meant to help you pass parameters in an easy, yet powerful way. Following example shows a sample query string and how to pass parameters to it.

Sample query string:

SELECT * FROM CUSTOMER WHERE FNAME LIKE ‘{0}’ AND LNAME LIKE ‘{1}’

Sample code to pass parameters or prepare queries:

 


Dim sParamArray(2) As String

sParamArray.SetValue(“Sukanya”, 0)

sParamArray.SetValue(“Singh”, 1)

SQLHelper.GetQueryString(“GetCustomerByName”,sParamArray)

 

 

To use the code shown above,

1.    Add text files to your data access project.

2.    Rename its extension to “.sql.qry” or whichever appropriate.

3.    Add your query to this file.

4.    Call the query from your data access code. No need to write long code from creating command and passing parameters.

 

Let me know if it works for you.

Thanks and have fun!!!

 

 

Do you use Information Expert?

Light Bulb

I’ve been recently involved in design as many of the teams I’ve been working with are starting newer projects. As we get on to design we had a lot of mention of using design patterns especially GOF(Gang Of Four).

One of the common problems I’ve faced using GOF is that it really does not fit every scenario especially when it comes to object modeling. It also does not tell me which object should do what all functions/responsibilities. It is also easy for developers with relatively lesser experience to forget about basic design principles like Low Coupling, High Cohesion, Modular Design while concentrating too much on design patterns.  

Few years back I had a chance to work with an Architect, who trained us on some very basic principles of design and code. One such concept I learned was Information Expert Pattern

It has since then served as a guiding principle, whenever i get in to design. It states that responsibility should be assigned to the information expert—the class that has all the necessary information.

Information expert not only enables you to keep the design simple, it also makes it a lot more easier to write code for reuse if followed religiously throughout the design.

The details of this can be found in the book Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development  by Craig Larman.

Some other references :

If you have used Information Expert before. Let me know your experiences.

Project Risks

·         No vision? You may lose track of where you are going and may be easily distracted on detours.
·         No process? Without a common process, the team may have miscommunications and misunderstandings about who is going to do what - and when.
·         No plan? You will not be able to track progress.
·         No risk list? You may be focusing on the wrong issues now and may explode on an unsuspected mine 5 months from now.
·         No business case? You risk losing time and money on the project. It may be cancelled or go bankrupt.
·         No architecture? You may be unable to handle communication, synchronization, and data access issues as they arise; there may be problems with scaling and performance.
·         No product (prototype)? As soon as possible, get a product in front of the customer. Just accumulating paperwork doesn’t assure you or the customer that the product will be successful-and it maximizes risk of budget and schedule overruns and/or outright failure.
·         No evaluation? Don’t keep your head in the sand. It is important to face the truth. How close are you really to your deadline? To your goals in quality or budget? Are all issues adequately being tracked?
·         No change requests? How do you keep track of requests from your stakeholders? How do you prioritize them? And keep the lower priority ones from falling through the cracks?
·         No user support? What happens when a user has a question or can’t figure out how to use the product? How easy is it to get help?

Do you agree?

MDI Windows in WPF(Post 1, Learning)

One of the graphics features of many windows applications which we are probably most comfortable using is multiple document interface. I am a software developer constantly trying my hand on newer technologies. 

 These days i am evaluating WPF, Visual Studio .NET 2008 and Expression Blend(tool for creating XAML). WPF is especially a new concept for Visual Basic developers and they may find it a little difficult to understand in the beginning, but i am sure once they understand a few basic classes of the new framework they would love the new features.

Going through the web i found that there is a tremendous demand for a MDI Window feature with in WPF and it is not included with in the first version of it. I thought it would be a good exercise to try and learn WPF while constructing classes for MDI.

Studying through web I’ve found that we’ll need to understand the architecture and the very facade which lies at the base of Windows Presentation Framework.

http://msdn2.microsoft.com/en-us/library/ms750441.aspx is a good start.

 Going through article i found that i need to understand the four basic elements that define the facade. They are

1. UIElement
2. ContentElement
3. FrameworkElement
4. FrameworkContentElement

Here is a sample code i’ve put together for supporting multiple windows.

http://cid-b3dbeec391c45395.skydrive.live.com/self.aspx/Public/Source%20Code/MDIWindow.zip

I am trying to also add elastic animation to window maximize, move and restore  functions. I’ll post another update once i am done.

 

Have a great time meanwhile.

  :)

Sunil