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:
- Create a class that will represent your object.
- 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>
);
- 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.