.Net Linq DataSet Проблемы (левые внешние объединения) - PullRequest
0 голосов
/ 22 сентября 2009

У меня есть 3 sql таблицы SourceKeys, Channels и ChannelTypes. Эти таблицы запрашиваются, и их данные хранятся в таблицах данных в моем наборе данных.

Что мне нужно, это:

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

но в форме linq ... Я немного новичок в linq и прочитал кучу статей msdn, но мне нужна помощь, чтобы преодолеть трудности.

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");

Полученная ошибка говорит о том, что channels.Field<int>("channelID") не может быть нулевым ... Я пытался использовать <int?>, но это не сработало.

Ответы [ 2 ]

2 голосов
/ 22 сентября 2009

Я кое-что перепутал ... похоже, это сработает.

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")
                     };
2 голосов
/ 22 сентября 2009

FWIW, я считаю, что код сложнее для понимания, чем простой вызов DataTable.Select , который также позволяет фильтровать, а также сортировать по родительским или дочерним таблицам, если необходимо.

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

Конечно, предполагается, что между таблицами определено DataRelation s.

Единственное, на что я не на 100% уверен, что вы могли бы сделать, это отсортировать по каналам в методе Select, так как эта таблица является родственным ключом источника, а не родителем / дочерним отношением.

РЕДАКТИРОВАТЬ: другой подход, который вы, возможно, захотите рассмотреть: если у вас есть (вложенные) отношения данных, то, возможно, DataSet.GetXml (), а затем запросить это с помощью LinqToXml?

...