4

I am using web forms, C#, Asp.net. As we all know, in this model UI and business logic are often mixed in. How do I separate these effectively?

The example I would like to use is: I have a GridView and a DataTable (GridView binds to the DataTable and DataTable is fed from the stored procedure).

I would like the GridView (UI) and DataTable (business logic) to be decoupled.

Is it worth it to write an wrapper for DataTable? Are there practical patterns that have been proved and tested that you could recommend to be followed?

If someone with experience could shed some light, that would be awesome. And, as a final note I would like to say that ASP MVC is not an option right now, so don't recommend it.

My database access layer returns a DataTable. Note that I HAVE to use this database layer as this is a company policy.

MvanGeest
  • 9,536
  • 4
  • 41
  • 41
sarsnake
  • 26,667
  • 58
  • 180
  • 286

3 Answers3

2

I went through this recently while decoupling much the same thing from our UI layer.

You can see my progress here and here.

In my opinion, A DataTable does not represent business logic. Specifically, it's data pulled directly from the database. Business logic turns that data into a truly useful business object.

The first step, then, is to decouple the DataTable from the Business object.

You can do that by creating objects and List<object> that make up DataTables and Collections of DataTables, and then you can make a ListView that displays those Objects. I cover the latter steps in the links I posted above. And the former steps are as easy as the following:

  1. Create a class that will represent your object.
  2. iterate through your DataTable (or DataSet, or however you retrieve the data) and shove those fields into properties of that object (or that List<T>);
  3. return that List to the Gridview or ListView to display.

This way your ListView or Gridview won't be tightly coupled to the method that you are retrieving your data. What happens if you decide to get your data from a JSON query or a XML file later on? Then you'd have to build this into there.

Step 1 - Getting Data From Database

There are multiple methods to get data from a database, there's no way I can go through all of them here. I assume that you already know how to retrieve data from a database, and if you don't, there are quite a few links to follow. Let's pretend you've connected to the database, and are using an SQLDataReader to retrieve data. We'll pick up there.

Class Diagram

Foo
----
id
Name
Description

And here's the method:

 private void FillDefault(SqlDataReader reader, Foos foo)
        {
            try
            {
                foo.id = Convert.ToInt32(reader[Foo.Properties.ID]);
                foo.Name = reader[Foo.Properties.NAME].ToString();
                    
                
             if (!string.IsNullOrEmpty(
                reader[Foo.Properties.DESCRIPTION].ToString()))
                 foo.Description = 
                 reader[Foo.Properties.DESCRIPTION].ToString();
             else foo.Description = string.Empty;
            }
            catch (Exception ex)
            {
               throw new Exception(
               string.Format("Invalid Query. 
               Column '{0}' does not exist in SqlDataReader.", 
               ex.Message));
            }
        }

Once that happens, you can return a list by going through that process in a while loop that targets the SQLDataReader.Read() function.

Once you do that, let's pretend that your Foo being returned is a List. If you do that, and follow the first link I gave above, you can replace Dictionary<TKey, TValue> with List<T> and achieve the same result (with minor differences). The Properties class just contains the column names in the database, so you have one place to change them (in case you were wondering).

DataTable - Update Based on Comment

You can always insert an intermediate object. In this instance, I'd insert a Business Layer between the DataTable and the UI, and I've discussed what I'd do above. But a DataTable is not a business object; it is a visual representation of a database. You can't transport that to the UI layer and call it de-coupled. They say you have to use a DataTable, do they say that you have to transport that DataTable to the UI? I can't imagine they would. If you do, then you'll never be de-coupled. You'll always need an intermediate object in between the DataTable and the UI layer.

Community
  • 1
  • 1
George Stocker
  • 57,289
  • 29
  • 176
  • 237
  • I am having difficulty following your links. It may be because your situations are specific portions of the process, while for me this is the first time and I would like to start at the beginning, not with Dictionary. – sarsnake Mar 26 '09 at 18:48
  • Ok; fair enough. I can expand my answer, if you'd like. – George Stocker Mar 26 '09 at 18:54
  • I am going to correct myself. I HAVE to use DataTable object as this is what my data layer returns which is a company policy - we all have to use this data access class. How would I go about decoupling then? – sarsnake Mar 26 '09 at 19:02
  • thanks, hmmmm, in my case I guess i will have to convert DataTable to List. At this point, I will have to ask what is the advantage of converting an object that is made for GridView to a generic List? – sarsnake Mar 26 '09 at 19:11
  • i think in my scenario creating a class that inherits from DataTable is more applicable. Then, I can manipulate it as a response to UI events. Actually, maybe not - that's pretty much what I am doing now. I am not sure if it's worth it to decouple given that I have a constraint to use DataTable. – sarsnake Mar 26 '09 at 19:18
  • no i don't have to transport DataTable to UI layer. I do have to use dataTable when getting data (through data access layer). So the next step after getting data would be, transporting the data to the Business layer object (such as List, dictionary, or whatever)? – sarsnake Mar 26 '09 at 20:20
  • If you keep the data as a datatable (or a class that derives from Datatable) then you'll always be tied to your current implementation. What happens if you add columns to the database and now have to get those out (it gets hairy). What happens if they change how you get this data? – George Stocker Mar 27 '09 at 11:45
  • The advantage of using a List or a business object is that you still use the DataTable to get the information from the database, but if that changes later on, you only need to make changes in your Data Access Layer, and not in both your DAL and your UI layer. – George Stocker Mar 27 '09 at 11:46
  • Gortok, one more question about this. Now I save the data table inside the session btwn postbacks. After separating I should still load List to and from Session inside the UI, correct? As far as I know, business layer should not be accessing Sessions object. Please clarify. – sarsnake Apr 06 '09 at 18:41
0

I'd start by decoupling the data table right into the trash can. Build a domain layer, and then some type of data access layer which deals with the DB (ORM recommended).

Then build a servicing layer which provides the data to the UI. All business logic should be within the service or the entities themself.

JoshBerke
  • 66,142
  • 25
  • 126
  • 164
  • no go for me. I HAVE to use DataTable object as this is what my data layer returns which is a company policy - we all have to use this data access class. – sarsnake Mar 26 '09 at 19:02
0

Consider implementing MVP (model view presenter) pattern. It gives you separation of biz logic through presenter interface, which also allow better unit testing capabilities. Your codebehind of aspx page is then just connector of events and getter/setter of properties. You can find it in MS pattern&practices enterprise application blocks (CAB - composite application block - if i'm not mistaking).
You can read more about it here: http://msdn.microsoft.com/en-us/magazine/cc188690.aspx
But also going from DataTable/DataSets to objects (POCO) is preferred.

Hrvoje Hudo
  • 8,994
  • 5
  • 33
  • 42