CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Eric Wise

Business & .NET

Custom Queries in Easy Assets .NET

Here's an example of what I love about the Domain Manager pattern I've developed in Easy Assets .NET as far as making things easily extendable for you developers out there.

Let's say that we have a table of Employees.  The table has the following fields: EmployeeID, FirstName, LastName, DepartmentID, and JobDescriptionID.  My domain manager object exposes two functions for getting lists of data from the database: GetList() and GetSummaryList().

GetList() returns a strongly typed collection of Employee Objects

GetSummaryList() returns a datatable

Each of these functions is exposed in the DAO class and takes a parameter of type EmployeeQuery.  EmployeeQuery exposes an employee object to optionally search on.  What this allows me to expose to you developers is the concept of searching by properties of an Employee object.  That is to say if you want to see a list of employees whose last name starts with 'W' you would create an EmployeeQuery with an Employee object inside it whose lastname property is set to 'W'.

    Public Shadows Function GetSummaryList(ByVal query As EmployeeQuery) As DataTable
        Dim mySQL As New System.Text.StringBuilder
        Dim params As New ArrayList
 
        mySQL.Append("SELECT * FROM Employees WHERE 1=1 ")
 
        If Not IsNothing(query.Employee) Then
 
            Dim p As SqlClient.SqlParameter
            If Not IsNothing(query.Employee.LastName) AndAlso query.Employee.LastName.Length > 0 Then
                mySQL.Append("AND LastName LIKE @LastName + '%' ")
                p = New SqlClient.SqlParameter("@LastName", query.MessageTopic.LastName)
                params.Add(p)
            End If
  
            If Not IsNothing(query.Employee.FirstName) AndAlso query.Employee.FirstName.Length > 0 Then
                mySQL.Append("AND FirstName LIKE @FirstName + '%' ")
                p = New SqlClient.SqlParameter("@FirstName", query.Employee.FirstName)
                params.Add(p)
            End If
 
            If Not IsNothing(query.Employee.DepartmentID) AndAlso query.Employee.DepartmentID > 0 Then
                mySQL.Append("AND DepartmentID = @DepartmentID ")
                p = New SqlClient.SqlParameter("@DepartmentID", query.Employee.DepartmentID)
                params.Add(p)
            End If
 
            If Not IsNothing(query.Employee.JobDescriptionID) AndAlso query.Employee.JobDescriptionID > 0 Then
                mySQL.Append("AND JobDescriptionID = @JobDescriptionID ")
                p = New SqlClient.SqlParameter("@JobDescriptionID", query.Employee.JobDescriptionID)
                params.Add(p)
            End If 
        End If
 
        Return ExecuteDataset(mySQL.ToString(), params, CommandType.Text).Tables(0)
    End Function

Notice how the method checks to see if you did populate the employee object and if so it begins checking the properties and building your where clause to filter accordingly.  This means that on the front end you can bind a datagrid to a datatable with only employee last name of 'W' as follows:

        'Create employee query to get only last names with 'W'
        Dim query As New EasyAssets.DAC.EmployeeQuery
        query.Employee = New EasyAssets.DAC.Employee
 
        query.Employee.LastName = "W"
  
        DataGrid1.DataSource = DomainManager.ListSummary(query)
        DataGrid1.DataBind()

As a developer using my product you don't need to know anything about what is going on in the datalayer.  All you need to know is to ask the DomainManager to give you the results of an employee query with an employee that looks like the one you passed in.

Pretty simple eh?  Anytime you want a parameterized query from a table this is all the code you need to write.  Someday soon I'll blog on how to modify the DAC class to do more specialized queries for custom reporting.

 



Comments

Dan said:

I really like the idea of receiving a "QueryClass" type as parameter for a search function. It specify clearly wich filter can be applied.

Thanks for sharing.

Btw, you have defined p As SqlClient.SqlParameter two times, you should've used the AirCode attribute. ;-)
# March 2, 2005 11:16 AM

Eric Wise said:

Oops, copy/paste error! Fixed now. =)
# March 2, 2005 11:18 AM

David Hayden said:

Very cool.

Rather than constructing the SQL outside of the query object, have you though about creating an abstract Query class with GetSql() and implementing differently for EmployeeQuery, etc, that is specific to the object.

You could do something like this (I did this very quick) -

[AirCode]
public abstract class Query
{
...

public abstract string GetSql();
}

public class EmployeeQuery : Query
{
...

public string GetSql()
{
// Generate specific code for Employee...
}

}

Then there is only one GetSummaryList for all your objects:

public IList GetSummaryList (Query query)
{
return ExecuteDataset(query.GetSql(), query.params, query.CommandType).Tables[0]
}

You will need to expose the Params and CommandType as properties as well from the query object, but I think you might get more mileage by encapsulating the SQL in the query objects.
# March 2, 2005 12:37 PM

Eric Wise said:

I had actually thought about something similar to that originally but I ended up moving away from it for a couple reasons.

1. I wanted all my sql to be in one spot. So if ever a developer is looking for where some sql exists they know it's in the DAO.

2. Similar reason was involved for not exposing params/command types etc to the query object. I felt that this would break the "cleanness" of having all things SQL related in the DAOs. My goal is basically to have queries simply carry query options, not so much be a sql based object.
# March 2, 2005 1:05 PM

Chris Wallace said:

I'm assuming you'd have to use a custom query string if you wanted != or NOT LIKE ?
# March 2, 2005 2:32 PM

Eric Wise said:

Yes, "NOT" queries or a mixed query would fall under a custom query object.

What I've done from the start is give a matched search (which is probably the most common) by default to show the pattern of how things are done.

When you get into NOT queries or queries that have a mix of = or NOT you're generally involved in writing a special review or report, so it lends itself to the custom query.

It will become more clear when I blog on it. =)
# March 2, 2005 3:18 PM

TrackBack said:

# March 3, 2005 5:57 AM

TrackBack said:

# March 3, 2005 6:04 AM

thilak said:

what is easyasset? is it a software? how can i use

# August 31, 2006 11:13 PM

Eric Wise said:

It's a free download from my web site: http://www.easywebapps.com

# September 1, 2006 2:42 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!