Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Grouping data from two classes into one class

Status
Not open for further replies.

JorgeBgs

Programmer
Jan 2, 2008
3
AU
This type of situation has always bothered me a bit.

I am building a website in C# 2.0 where users can post reviews of things. Currently I have classes called User, Comment and Review. The Review class inherits from Comment because it is basically a specialized type of Comment.

Now, when I am displaying a list of reviews and comments I need a couple of extra bits of information that are not in the Review or Comments class, e.g. the author's name and avatar.

Keeping performance in mind I make only two queries like this:

SELECT comment.*, user.Name, user.AvatarName FROM comment
INNER JOIN user ON user.UserId = comment.UserId

SELECT review.*, user.Name, user.AvatarName FROM review
INNER JOIN user ON user.UserId = review.UserId

What is the most elegant way to contain this data in c# objects? I'm not particularly fond of exposing raw DataSets to the UI layer. Ideally I want the UI layer to only deal with the c# objects which have been filled in the Data Access Layer.

If I was only getting comment data, I would just create a List of Comment objects. But in this case there is also a small subset of user data to put somewhere.

The options I came up with are:

1) Create a new class with properties for the Comment (or Review), the user's name and the avatar filename.

2) Fill the user's name and and avatar into a User object and just accept that the data is incomplete.

3) Fill the user's name and avatar into the Comment/Review object and expose them as read-only properties.

4) Give up and allow the UI layer to deal with the DataSet directly.

Any thoughts?
 
I don't understand. The first query returns a user name and an avatar, even if comments do not have them.

You may be better off with a query like:

Code:
SELECT *, NULL AS Name, NULL AS AvatarName FROM comment
UNION
SELECT * FROM review;

You can feed this to a factory that creates a review object if the name and avatar are given, and a comment object otherwise.

How those two objects behave is something you should decide for yourself. A comment may, for instance, return a transparent picture of the correct size for its avatar.
 
Hi thanks,
I think I should illustrate my data structure better. Bare in mind though that this is just an example, and I'm not particularly concerned with the database side of things, I'm interested in how to fill the data into OO objects.

OK, so I have three tables:

User (UserId, Name, AvatarName, Bio, Website)
Comment (CommentId, UserId, CommentText)
Review (OverallRating, CommentId)

These tables map directly to c# classes, except that in c# the relationship between Review and Comment is expressed via inheritance, rather than through the foreign key.

OK, so I can use whatever query is best to get data out of the database and then use whatever method is best to fill the data into c# objects - e.g using a factory as you suggest.

The main problem I have is this -

I am trying to deal elegantly with an incomplete subset of User data. In my example, my query is not returning the user's bio and website. If I then populate a user object from this query, its bio and website will not be set.

There may be no clue in the UI layer that the user's data
has not been completely loaded, so a UI developer may try to access the user's bio without realising it was never fetched from the database. This would result in a null reference exception. OK, it's not the worst thing in the world and would probably show up during testing, but its not very elegant.

The other thing is, in reality the User class may be quite large with many fields. If all I'm interested in is two short strings (the user's name and avatar filename), it seems wasteful to instantiate such a huge class.

So my problem is more related to the Business Entity/UI layers than the Data Access/Database layers.
 
What you need is an ORM that supports lazy loading like nhibernate. Then the ORm will only load those properties that the UI demands. You could implement some lazy loading yourself or use proxy objects (a proxy pattern means that you have a slimmed down version of the big user object but that is still related to each other, probably not the best explanation but google has better).

But your Domain entities shouldn't care less about this. Just make them how they should and then in the DAL use lazy loading.

BTW and ORM doesn't replace the DAL it just makes it eassier and faster to write.

Christiaan Baes
Belgium

My Blog
 
Or create a class which encapsulates your data classes, and exposes properties which act as a pass-thru to the encapsulated instances.

Think of it as a poor-man's view.
:)

Chip H.


____________________________________________________________________
If you want to get the best response to a question, please read FAQ222-2244 first
 
Thanks guys,

Yeah I think I'll go with Chip's idea which is the same as my number 1 option in my original post.

That way I can have "CommentView" and "ReviewView" classes with read-only properties that pass through to the data classes. E.g.

class CommentView
{
Comment _commentBody;
string _authorName;
string _avatarFilename;
public CommentBody { get { return _comment; } }
public string { get { return _authorName; } }
public string { get { return _avatarFilename; } }
}

It's a hassle to setup, but it prevents the UI layer from incorrectly accessing the Comment when it hasn't been fully loaded.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top