views:

451

answers:

2

I have 3 sql tables SourceKeys, Channels, and ChannelTypes. These tables are queried and their data is stored in datatables in my dataset.

What I need is this:

SELECT ...
FROM ChannelTypes ct 
LEFT OUTER JOIN Channels ch ON ct.channelTypeID = channelTypeID
LEFT OUTER JOIN SourceKeys sk ON ch.channelID = sk.channelID

but in linq form... I'm a bit new to linq and read a bunch of msdn articles but just need some help to get over the hump.

var sourceKeyQuery = 
    from ct in ds.Tables["ChannelTypes"].AsEnumerable()
     join ch in ds.Tables["Channels"].AsEnumerable()
     on ct.Field<int>("channelTypeID") equals ch.Field<int>("channelTypeID") into gj1
     from channels in gj1.DefaultIfEmpty()
     join sk in ds.Tables["SourceKeys"].AsEnumerable()
     on channels.Field<int>("channelID") equals sk.Field<int>("channelID") into gj2
     from sourceKeys in gj2.DefaultIfEmpty()
     orderby ct.Field<string>("channelType"), 
             channels.Field<string>("channel"),
             sourceKeys.Field<string>("sourceKeys")
     select (sourceKeys == null)?null:sourceKeys.Field<int?>("sourceKeyID");

The error I'm getting says channels.Field<int>("channelID") cannot be null... i tried using <int?> but it didnt work.

+2  A: 

FWIW, I find that code more difficult to understand than a simple call to DataTable.Select, which also allows filtering as well as sorting, by parent or child tables if needed.

var keys = ds.Tables["SourceKeys"].Select(...)
foreach (var key in keys)
{
    int id = key["sourceKeyID"];
    ...
}

Of course that assumes you have DataRelations defined between the tables.

The only thing I'm not 100% sure you could do is sort by channel in the Select method, since that table appears to be a sibling of source keys, rather than a parent/child relationship.

EDIT: the other approach you may want to consider: if you do have (nested) data relations, then perhaps DataSet.GetXml() and then query that using LinqToXml?

Si
I do have data relations setup, ill check this out
Chris Klepeis
I'll use that in the future, but that would only return records if sourcekey datatable rows exist (i believe)... I'm using this to populate a treeview so i need channelTypes and channels even if there are no sourcekeys present
Chris Klepeis
Ah...fair enough, but then wouldn't ds.Tables["ChannelTypes"].Select(..) also suffice? Anyway, you got it sorted :)
Si
A: 

I had a few things mixed up... looks like this will work.

var sourceKeyQuery = from ct in ds.Tables["ChannelTypes"].AsEnumerable()
                     join ch in ds.Tables["Channels"].AsEnumerable()
                     on ct.Field<int>("channelTypeID") equals ch.Field<int>("channelTypeID") into g_ch
                     join sk in ds.Tables["SourceKeys"].AsEnumerable()
                     on ct.Field<int>("channelTypeID") equals sk.Field<int>("channelID") into g_ct
                     from ch in g_ch.DefaultIfEmpty()
                     from sk in g_ct.DefaultIfEmpty()
                     select new 
                     {
                         channelTypeID = ct.Field<int>("channelTypeID"),
                         channelType = ct.Field<string>("channelType"),
                         channelID = (ch == null)?null:ch.Field<int?>("channelID"),
                         channel = (ch == null)?String.Empty:ch.Field<string>("channel"),
                         sourceKeyID = (sk == null)?null:sk.Field<int?>("sourceKeyID"),
                         sourceKey = (sk == null)?String.Empty:sk.Field<string>("sourceKey")
                     };
Chris Klepeis