Accepted answer

short explanation

it seems the portion of your question that may seem tricky is how to populate a custom class in the same fashion that the linq to sql ("l2s" from here on out) query does for the anonymous class.

based on your foreach loop i am guessing your custom classes are similar to these:

public class posttype
    public int postid { get; set; }
    public list<postcomment> postcomments { get; set; }
public class postcomment
    public int commentid { get; set; }
    public string title { get; set; }

the linq query should be equivalent to this t-sql statement:

select p.post_id,, c.title 
from post as p, comment as c
    p.post_id = @postid
    and p.post_isdeleted = 0  -- 0 is false
    and c.commentpostid = p.post_id

unlike the l2s version (see the detailed explanation section below for more info), this statement returns a flattened result with each row containing a p.post_id,, and c.title. if your posttype class represented an entry in the same way this would've been easily solved (i'm not advocating such a design; i'm merely commenting on how the design alters how it gets populated). the hierarchical relationship in the classes changes things.

also, your code showed a list<posttype> but a list is not required since there will always be one posttype because you're filtering on post_id. if that condition is removed, then you might get multiple matches with different postids where the other conditions are satisfied. if that's the case the code below would need to change.

that said, let's jump into some and populate the classes using a sqldatareader.

int postidinput = 42; // desired post_id to search for

// posttype delcared prior to getting the results
posttype posttype = new posttype()
    postid = postidinput,
    postcomments = new list<postcomment>()

 // database interaction starts here...
 // updated sql statement to use column name aliases for clarity when used by the sqldatareader
 string sqlstatement = @"select p.post_id as postid, as commentid, c.title as title
                         from post as p, comment as c
                             p.post_id = @postid
                             and p.post_isdeleted = 0  -- 0 is false
                             and c.commentpostid = p.post_id";

 string sqlconnectionstring = "..."; // whatever your connection is... probably identical to your l2s context.connection.connectionstring
 using (sqlconnection conn = new sqlconnection(sqlconnectionstring))
     sqlcommand command = new sqlcommand(sqlstatement, conn);
     command.parameters.addwithvalue("@postid", postidinput); // use parameters.add() for greater specificity

    sqldatareader reader = command.executereader();
    while (
        // postid was set based on input, but could be set here as well although it would occur repeatedly
        // if desired, uncomment the 2 lines below and there's no need to initialize it earlier (it'll be overwritten anyway)
        //int postid = int32.parse(reader["postid"].tostring());
        //posttype.postid = postid;
        int commentid = int32.parse(reader["commentid"].tostring());
        string title = reader["title"].tostring();

        // add new postcomment to the list
        postcomment postcomment = new postcomment
            commentid = commentid,
            title = title

    // done! posttype is populated...

// use posttype...

that should cover your scenario. however, for a much more detailed answer, keep reading!

detailed explanation (aka "teach a man to fish...")

let's say you couldn't figure out how to get the equivalent sql statement. while there are different ways to do so, i will concentrate on the fact that you are using l2s and explore some related options.

step 1: converting the linq query to sql (by "cheating")

you're in luck since there's a shortcut. converting your existing linq expression to sql is a slightly more convenient situation to be in than going backwards and translating sql to linq.

you can get the translated t-sql statement from your code by using either of these datacontext options:

note: i did say this was a shortcut. knowledge of sql is good to know, and to be clear i am not suggesting the use of generated output blindly. granted, the sql may differ from what you expect sometimes, nonetheless it provides a decent starting point. you may tweak it if needed.

use either of these methods and copy the result - you'll need it for step 2.

example datacontext.getcommand() usage:

var query = /* your l2s query here */;
string sqlstatement = context.getcommand(query).commandtext;    // voila!

to get the result either set a breakpoint and copy its value, check it out in the immediate window, or display it somewhere (console.writeline etc.).

example datacontext.log usage:

context.log = console.out;

queries executed on that context will have their sql statements dumped to the console window. you may copy it from there. to dump them elsewhere, such as to the debug output window, check out these links:

step 2: with the sql statement in hand, use it in

now that you have the sql statement we can use it in of course you could use a stored procedure as well and it shouldn't be hard to substitute it.

before using it though, you'll probably want to clean the statement up. i used a similar query locally to get this and your generated statement probably resembles this:

select [t0].[post_id], [t1].[id], [t1].[title], (
 select count(*)
 from [comment] as [t2]
 where [t2].[id] = [t0].[post_id]
 ) as [value]
from [post] as [t0]
left outer join [comment] as [t1] on [t1].[commentpostid] = [t0].[post_id]
where ([t0].[post_id] = @p0) and ([t0].[post_isdeleted] = 0)
order by [t0].[post_id], [t1].[id]

notice the embedded select count(*)? the l2s query never requested the count, yet the result requests the count of the equal ids used on the join. also notice that there are no aliases for the columns. you would refer to the columns based on their actual names (ie. post_id versus postid). in addition, the sql parameters are named @p0...@pn and a default sort order is applied. you could copy/paste this into the sqldatareader used earlier, but you would need to rename the columns and parameters to match.

a cleaned up version of the above is reproduced below with renamed parameters and unnecessary parts commented out (if this approach is taken test it out to ensure it's equivalent to what is expected):

select [p].[post_id] as postid, [c].[id] as commentid, [c].[title] as title--, (
-- select count(*)
-- from [comment] as [t2]
-- where [t2].[id] = [t0].[post_id]
-- ) as [value]
from [post] as [p]
left outer join [comment] as [c] on [c].[commentpostid] = [p].[post_id]
where ([p].[post_id] = @postid) and ([p].[post_isdeleted] = 0)
--order by [t0].[post_id], [t1].[id]

the above can now be used with the sqldatareader from earlier.

a more direct query could've been generated if the l2s query was in the format of a selectmany, such as:

var query = from arow in
            from c in context.comment
            where arow.post_id == id && arow.post_isdeleted == false
                  && c.commentpostid == arow.post_id
            select new

the selectmany l2s query generates a sql statement similar to this:

select [t0].[post_id], [t1].[id], [t1].[title]
from [post] as [t0], [comment] as [t1]
where ([t0].[post_id] = @p0) and ([t0].[post_isdeleted] = 0)
      and ([t1].[commentpostid] = [t0].[post_id])


while this detailed explanation might seem overwhelming, there's an easy way to have this information at your fingertips. if you haven't given linqpad a try then i highly recommend it - it's free too! linqpad will show you the results of your l2s queries, has a sql tab to view the generated sql, and also shows the lambda expression used (the above query syntax is shown as the lambda/extension equivalent). on top of that, it's a great tool for general purpose c#/ (including linq to objects/xml), and sql coding with database support and much more.

here's a tiny screenshot of linqpad showing some of the topics discussed earlier:


i didn't want to take up more page real estate than i already have so click here to see the image in its original size.

if you made it this far, congrats! :)


i can't test this but something along the lines of:

    post p 
where == 'id' and 
    isdeleted = false
inner join comment c on c.commentpostid = p.post_id

i capitalize keywords for readability but for the dbs you're using you might need to change that.


select post_id, id, title from postcomments pc
where post_id = @id and exists(
    select post_id form post p where p.post_id = pc.post_id and isdeleted = false

use a datareader to get the data & just load it in a list with your custom classes


if you mean that there is a relation between posts and postcomments tables and there are repeated columns in both tables and one comment could be related to more than one post so you can easily create two commands:

-select * from posts where post_id = id and isdeleted = 0;
-select * from postcomments where id = cid;

and then execute them using sql command adapters on two data tables. and then:

foreach(datarow dr in poststable.rows)
 //fill the post custom class
 secondtable.defaultview.rowfilter = string.format("postid = {0}",dr["postid"]);
 foreach(datarow r in secondtable.rows)
  //fill the comments custom class

if this is not your case, so could you try to clarify your database structure?


use sql profiler to catch the generated query. copy to new stored procedure and repair input parameters. create (save) and use it :)

Related Query