Consider the following requirement for building a forum App
Parent Post
- Child Post1
- Child Post1-1
- Child Post1-2
- Child Post1-2-1
- Child Post2
- Child Post
- Child Post3
Table Structure
tblPost -
- PostId
- ChildPostId
- Title
- Post Content
- UserName
=====================
I can retreive this kind of data using a recursive CTE. I am not sure this is the best approach.
Questions
What is the best way to retreive this data using SQL?
Is there a better way to load this data using an ORM?
If we go the SQL route, what is the best way to Load this data into a class like shown below:
public class Post { public int PostId {get;set;} public string PostTitle {get;set;} public string PostContent {get;set;} public string PostedBy {get;set;} public IEnumerable<Post> ChildPosts {get;set;} }
How about displaying this kind of data say using the razor syntax for a view??
According to your comment you are open to suggestions about improving your current database schema in which you basically have a
post_id
and achild_post_id
columns to perform the hierarchical relationship.So let's proceed:
I would recommend you taking a look at the following article which illustrates a very nice technique for managing such hierarchical data in a very efficient way. It uses the The Nested Set Model in which you define sets with left and right nodes and then you are able to build the entire tree with a single SQL query:
There are ways doing this using an ORM such as NHibernate and EF but I will leave this for next time. You might consider splitting your questions into multiple SO questions as the subject is quite broad. If you learn how to do this using plain ADO.NET you will gather far better understanding of the underlying techniques that are involved so that tomorrow you decide to use such an ORM you will already know what to look for in order of efficient queries.
Once you have constructed your hierarchical model it's extremely simple. All you have to do is to define a custom display template for the
Post
type in which you would invoke the display template for all child posts.So assuming the following model:
and the following controller (in which I obviously have hardcoded the values but after reading the tutorial I have linked to in the beginning of my post you will be able to construct this model with a single SQL query):
and then you would have an
~/Views/Home/Index.cshtml
view:and of course a corresponding display template (
~/Views/Home/DisplayTemplates/Post.cshtml
) which will be recursive in our case to render the full tree:and of course the final result is what one might expect:
UPDATE:
As requested in the comments section here's one example of how one might populate the Post model. Let's assume that you have followed the nested set model to design your database table:
and that you have filled it with the posts:
Now you could fetch them.
But as always before actually doing something you describe what you want to do. That is: you define a contract:
Now you get to the doing. In this case we will use plain ADO.NET to query the database and built the Post object. We will use an iterative algorithm with a stack to build the tree but you could also use a recursive algorithm:
Now that we have this repository we could bring the pieces together:
and the last part is to configure your favorite Dependency Injection framework to inject the desired implementation of the repository and since we have only one so far that would be
PostsRepositoryAdoNet
. And if tomorrow you decide to switch to an ORM all you have to do is to write the corresponding repository implementing theIPostsRepository
interface.