Community Approach to business object using DataTable.

J

jehugaleahsa

Hello:

I am trying to find what is the very best approach to business objects
in Windows Forms. Windows Forms presents an awesome opportunity to use
DataTables and I would like to continue doing so.

I have worked with dynamically generated DataTables with customized
DataRows. However, these classes are usually pretty limited. For
instance, you are limited to a select few data types and you can't
deal with nulls as well as desired (in my experience).

I could create dummy business objects that have properties with
underlying private fields. However, this eliminates DataTables
altogether. It also means giving up constraints, some type-checking,
etc.

As a remedy, I have been creating business objects that each recieve a
DataRow. Each property in the business object accesses a different
DataRow field. That way changes to my business object will affect the
underlying DataTable, so data adapters will work.

While this works, I want to make sure it is the best way. What do you
do for business objects? What has Microsoft done to make life easy and
what is the recommended way to go? While I am happy with my setup, I
am curious to see what really is the recommended way, the right way.

Thanks,
Travis
 
M

Marc Gravell

I very rarely touch DataTable et al. Normally, just regular classes
with properties suffice, and allow full data-binding - and contrary to
your view, I think it *improves* my ability to enforce business rules
etc.

If you want to get the code-generation benefit of DataTable, with the
strength of raw classes, then look at ORM tools. Most recently
(VS2008, .NET 3.5) LINQ-to-SQL would be of interest; but NHibernate is
also very popular and has had more time to "bed in".

Marc
 
N

Nicholas Paldino [.NET/C# MVP]

Travis,

Why do you say that using buisness objects gives up constraints? You
would code the constraints into your property assignments and/or methods
which modify the underlying properties.

Also, the type checking wouldn't be gone either, unless you were
exposing properties as objects?

Using the DataRow as the underlying mechanism is a pretty good idea.
However, many people find data rows inefficient (wrapped or not). If they
work for you, then by all means, use them (what applies for everyone else
isn't always the case for you).

Personally, I am using interfaces as a model definition (with an
underlying metadata type system) which is used to manage the underlying
table structure, as well as an engine which dynamically provides the
interface implementations based on the model definition. All
constraint/modification code is handled outside of the model (I personally
believe in separating the data model/storage from the logic that modifies
it).
 
J

jehugaleahsa

Travis,

    Why do you say that using buisness objects gives up constraints?  You
would code the constraints into your property assignments and/or methods
which modify the underlying properties.

You are right. It just happens that in my environment, constraints are
rarely checked at all until a SQL is ran. This is probably not the
best thing in the world. What little constraints we do have in code
are provided via DataSet. This is mostly to ease validation table look-
ups, primary key and other foreign constraints. We usually are not
that concerned with the format of the data, as long as a number is a
number and a date is a date, which we do do in our business objects.
    Also, the type checking wouldn't be gone either, unless you were
exposing properties as objects?

I am afraid that I will declare a database type to be an integer when
a long would be more appropriate. I am afraid of limiting the size of
a field in my application when the database was designed otherwise. I
have yet to find a really steadfast way of getting the associated .NET
type given a DB specification (we work in Oracle, mostly).
Fortunately, FillSchema on a DataAdapter tends to find the best .NET
type for me. I usually look at the DataTable column type to figure out
what I should use. (This is also a bit of a hassle)
    Using the DataRow as the underlying mechanism is a pretty good idea.
However, many people find data rows inefficient (wrapped or not).  If they
work for you, then by all means, use them (what applies for everyone else
isn't always the case for you).

They do work for our project. I am currently working on a project
where I am not allowed to use a library I wrote a few months ago. My
library *can* use DataRow, but usually uses dynamically generated
business objects that store data in an IDictionary<string, object>.
Since my current project is/was so dependent on generated DataTables,
I just did what seemed easiest. However, it has brought to light my
question here. It really made me wonder if I was far off my mark and
whether wrapping a DataRow was such a good idea after all. There are
some cases where I can see it as a definite disadvantage because it
then *requires* me to use DataTable even when working with non-
database information (since I use a base class that handles DataRow
editing/extraction). I can of course deviate from the base class, but
it makes the code seem dirtier to me (I like consistency).
    Personally, I am using interfaces as a model definition (with an
underlying metadata type system) which is used to manage the underlying
table structure, as well as an engine which dynamically provides the
interface implementations based on the model definition.  All
constraint/modification code is handled outside of the model (I personally
believe in separating the data model/storage from the logic that modifies
it).

This sounds very much like my library that I wrote a few months ago.
My library had an abstract base class. I had a small tool that took
the database specification, generated recommended property types and
names and allowed them to be customized. The generated class had
Attributes such as TableAttribute and ColumnAttribute, and privilege
properties. The abstract class managed properties using an
IDataWrapper interface that could essentially pointed to an
IDataRecord, DataRow, IDictionary<string, object>, etc. I had a
historical business object as well that kept track of changes for me.
And that is just the Business Object side - there are also classes for
dynamically generating SQL in a database-independent way, classes for
simplifying disconnected/connected SQL execution/data management,
blah, blah. It essentially had everything my little heart
desired . . . and most of it worked well.

It has been wonderful for ASP .NET web applications; I just wish I
were allowed to use it on my current application.

Well, I guess I am okay to keep going the route I am going down.
Thanks for the thoughts.
 
N

Nicholas Paldino [.NET/C# MVP]

Travis,

I have to ask, why are you not allowed to use the library you developed?
If it works, then I don't see the reason.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Travis,

Why do you say that using buisness objects gives up constraints? You
would code the constraints into your property assignments and/or methods
which modify the underlying properties.

You are right. It just happens that in my environment, constraints are
rarely checked at all until a SQL is ran. This is probably not the
best thing in the world. What little constraints we do have in code
are provided via DataSet. This is mostly to ease validation table look-
ups, primary key and other foreign constraints. We usually are not
that concerned with the format of the data, as long as a number is a
number and a date is a date, which we do do in our business objects.
Also, the type checking wouldn't be gone either, unless you were
exposing properties as objects?

I am afraid that I will declare a database type to be an integer when
a long would be more appropriate. I am afraid of limiting the size of
a field in my application when the database was designed otherwise. I
have yet to find a really steadfast way of getting the associated .NET
type given a DB specification (we work in Oracle, mostly).
Fortunately, FillSchema on a DataAdapter tends to find the best .NET
type for me. I usually look at the DataTable column type to figure out
what I should use. (This is also a bit of a hassle)
Using the DataRow as the underlying mechanism is a pretty good idea.
However, many people find data rows inefficient (wrapped or not). If they
work for you, then by all means, use them (what applies for everyone else
isn't always the case for you).

They do work for our project. I am currently working on a project
where I am not allowed to use a library I wrote a few months ago. My
library *can* use DataRow, but usually uses dynamically generated
business objects that store data in an IDictionary<string, object>.
Since my current project is/was so dependent on generated DataTables,
I just did what seemed easiest. However, it has brought to light my
question here. It really made me wonder if I was far off my mark and
whether wrapping a DataRow was such a good idea after all. There are
some cases where I can see it as a definite disadvantage because it
then *requires* me to use DataTable even when working with non-
database information (since I use a base class that handles DataRow
editing/extraction). I can of course deviate from the base class, but
it makes the code seem dirtier to me (I like consistency).
Personally, I am using interfaces as a model definition (with an
underlying metadata type system) which is used to manage the underlying
table structure, as well as an engine which dynamically provides the
interface implementations based on the model definition. All
constraint/modification code is handled outside of the model (I personally
believe in separating the data model/storage from the logic that modifies
it).

This sounds very much like my library that I wrote a few months ago.
My library had an abstract base class. I had a small tool that took
the database specification, generated recommended property types and
names and allowed them to be customized. The generated class had
Attributes such as TableAttribute and ColumnAttribute, and privilege
properties. The abstract class managed properties using an
IDataWrapper interface that could essentially pointed to an
IDataRecord, DataRow, IDictionary<string, object>, etc. I had a
historical business object as well that kept track of changes for me.
And that is just the Business Object side - there are also classes for
dynamically generating SQL in a database-independent way, classes for
simplifying disconnected/connected SQL execution/data management,
blah, blah. It essentially had everything my little heart
desired . . . and most of it worked well.

It has been wonderful for ASP .NET web applications; I just wish I
were allowed to use it on my current application.

Well, I guess I am okay to keep going the route I am going down.
Thanks for the thoughts.
 
J

jehugaleahsa

Travis,

    I have to ask, why are you not allowed to use the library you developed?
If it works, then I don't see the reason.

I have posted to this forum before about my lead developer. He is a
little outdated and is afraid to use code that will eventually fall on
him to maintain. If It is too hard for him to grasp right away, he
shys away. It is understandable; I wouldn't want to be him if I got
hit by a bus. However, with the size of this project, it is no
question to whether there will be some extreme complexities.

We are fairly fortunate here because most of our applications simple
display data from database tables. There are only a limited number of
applications that actually manipulate data in any way. We can get by
with just SQL, most of the time.

The problem is that my lead develop knows I am properly trained in
computer science and that I know the fundamentals about OOP, Software
Engineering, data structures and algorithms. He is not. He is very
careful about limiting me to as little theoretical application as
possible. I am often forced to do something that is slightly redundant/
inefficient so that he is okay with it. Fortunately for me and the
project, he is fairly busy most of time with user requests and bug
fixes, so I can do some things more properly without his criticism.
Since the project is a retool, there is no worry about breaking
existing code. I figure I should get it to be as correct, simple and
elegant as possible before he gets his hands on it. A lot of his work
has been redone by my peer and myself, in an effort to standardize and
simplify.

When we first started the project 6 months ago, my lead developer was
taught the basics about DataSets. However, he missed his mark by
putting every DataTable in its own DataSet and totally disregarded
relations and constraints. He used DataTables generated by the Visual
Studio DataTable designer. He put all the SQL directly inside the
DataTable classes. The problem was that his approach totally locked us
to creating massive amounts of DataTables and using predefined types
for all our properties. This also meant our properties had horrible
names that were hard to conceptualize.

When I came on to the project I immediately saw problems with this
approach. Most of the interface was not functional and the process for
creating a form/DataTable was complicated. I disregarded his approach
and simply started wrapping non-type-safe DataRows in business objects
of my own design. I was able to pump out most of the forms in a day's
time with far less code. Of course my approach still lacks constraint
checking, but we're not losing anything we had before. Since most of
our forms are simply displaying GridViews of information and allowing
for simple adding, deleting, updating, there was never a reason for
anything very complicated.

Due to my decision, I have finished nearly every form in the retool
(about 90+ forms). It has been interesting because when I started, I
had never done automatic data binding on Windows Forms. As I went
along (with lots of help from this forum) I was able to find better
ways to do binding and have gone back and updated my older forms. I
also wrote a simple business object generator class bases on my
library's code that generates simplified business objects for us.

In the long run, my peer and I are keeping it to ourselves that what
my lead gave us months ago looks nothing like what it does now. Most
of his work has been redone completely. All he sees is that his code
works now and that things are far more consistent. We have made him
aware of our plans, but he seems completely disinterested in learning
the new approach. It is really disappointing and at the same time
irritating. So, what he feared most of all has taken place and he just
let it happen. If I get hit by a bus, he is going to have a hard time
trying to figure out the approach we are now taking, even though we
are trying to explain it to him now. It is simple enough - we aren't
rocket scientists; although having programming training in the past 10
years would definitely make it easier.

My peer is not a trained programmer either, but he is very ambitious.
We share a lot of concerns and desires for the project. He and I often
share our findings and improve upon them. He is always a little crabby
at me for finding just slightly better ways of doing things every day
- especially when it would have saved him a lot of time. Oops. He is
my backup if I get hit by a bus. I would feel bad for him though
because he has a tendency to give into my lead and doesn't have the
training to know the difference between a good design decision and
something that sounds good.

I suppose the three of us should sit down and have a meeting called,
"Getting you back into the project". I hold nothing against my lead
developer, except that he is so rigid. He is swamped with user
requests and bug fixes so I can imagine it hard for him to concentrate
on the retool. He definitely should have spent more time designing and
checking out his alternatives. He got an awesome tool like Visual
Studio 2005 and he hardly knows how to use it.

So, really I am looking for something I can say to my lead, "Look,
this is what some of the biggest and greatest names in Windows
development are doing and there is good reason for it. Let's take this
route and learn to do this project right the first time though." And
now that we are so far through, I want to be able to say if he ever
gets on my case about it, "I looked at the options; this is the best
way; this is what we are doing." He and I both need to know that I did
my research and didn't just do what was self-gratifying.

Thank you for your response,
Travis
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top