linq (правое) соединение не возвращает правильное количество объектов

У меня есть вопрос о объединениях в LINQ. В настоящее время я конвертирую приложение доступа в .NET, где данные извлекаются из двух разных баз данных на двух разных серверах. В старом приложении данные можно было получить одним запросом:

SELECT *, tbl2.Descr, tbl2.Form FROM tbl2 RIGHT JOIN tbl1 ON tbl2.proId2 = tbl1.proId

Я обнаружил, что один из способов сделать это в .NET — получить две таблицы по отдельности, а затем соединить их с помощью LINQ. У меня нет опыта работы с LINQ, поэтому я могу ошибаться в своей логике или коде, потому что не могу заставить его работать.

Сначала я попытался сделать обычное соединение (без права), но затем возвращаются только 18 строк, когда две таблицы содержат почти 2000 строк. Я также проверил данные, и это определенно должно привести к большему количеству строк, пустых ячеек не так много. Итак, я собрал правое/левое соединение, но на самом деле это приводит к ошибке. Когда я отлаживаю его, все в порядке, когда выполняется инструкция LINQ, но когда я перехожу к foreach, отображается ошибка, и ошибка фактически указывается в инструкции linq, говоря, что таблица2 пуста. Когда я проверяю таблицу 1, я также вижу только 22 строки данных.

Что я делаю неправильно?

DataTable dtTarget= data1.Clone();
var dt2Columns = data2.Columns.OfType<DataColumn>().Select(dc =>
     new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping));
var dt2FinalColumns = from dc in dt2Columns.AsEnumerable()
                    where dtTarget.Columns.Contains(dc.ColumnName) == false
                              select dc;

dtTarget.Columns.AddRange(dt2FinalColumns.ToArray());

var results = from table1 in data1.AsEnumerable()
              join table2 in data2.AsEnumerable() 
              on table1.Field<String>("proId") equals table2.Field<String>("proId2")
              select table1.ItemArray.Concat(table2.ItemArray).ToArray();

foreach (object[] values in results)
            dtTarget.Rows.Add(values);

Внешнее соединение:

var results = from table1 in data1.AsEnumerable()
              join table2 in data2.AsEnumerable() on table1.Field<String>("proId")     equals table2.Field<String>("proId2") into t_join
              from table2 in t_join.DefaultIfEmpty(null) select table1.ItemArray.Concat(table2.ItemArray).ToArray();

person LittleWhiteFairy    schedule 14.02.2013    source источник


Ответы (1)


Я заметил, что вы используете строки в качестве ключей соединения. Возможно, сравнение строк отличается в разных средах (доступ и .net). Доступ может использовать сравнение без учета регистра, в то время как по умолчанию .net учитывает регистр.

Чтобы заставить .net использовать сравнение без учета регистра, вот первый запрос:

var results = data1.AsEnumerable()
  .Join(
    data2.AsEnumerable(),
    row1 => row1.Field<String>("proId"),
    row2 => row2.Field<String>("proId2"),
    (row1, row2) => row1.ItemArray.Concat(row2.ItemArray).ToArray(),
    StringComparer.InvariantCultureIgnoreCase); //and now caps are ignored.

и второй запрос:

var results = data1.AsEnumerable()
  .GroupJoin(
    data2.AsEnumerable(),
    row1 => row1.Field<String>("proId"),
    row2 => row2.Field<String>("proId2"),
    (row1, row2s) => new {Row1 = row1, Row2s = row2s},
    StringComparer.InvariantCultureIgnoreCase)
  .SelectMany(
    x => x.row2s.DefaultIfEmpty(null)),
    (x, row2) => row2 == null ? x.Row1.ItemArray : x.Row1.ItemArray.Concat(row2.ItemArray).ToArray()
  );
person Amy B    schedule 14.02.2013
comment
Хорошо, первый запрос ничего не меняет, но это нормально, потому что мне действительно нужен второй. Теперь работает без ошибок и столбцы второй таблицы добавляются к первой, но большинство значений добавленной таблицы пустые. Я думаю, что очень странно, что некоторые ключи найдены, но большинство из них нет. И вы были правы, одна таблица из доступа, а другая из сервера sql. - person LittleWhiteFairy; 14.02.2013
comment
Я нашел, что было не так. Ключи пришлось подрезать. Так что теперь все работает. Спасибо Давид за помощь - person LittleWhiteFairy; 15.02.2013