LINQ to DataSet - объединения и проблемы GridView - PullRequest
2 голосов
/ 08 апреля 2011

У меня есть три DataTables, которые мне нужно объединить и использовать объединенные данные в качестве источника данных для GridView. Первый (localSQLTable) заполняется с помощью запроса к базе данных MS-SQL. Вторые два (serviceResponse.Tables(0) и serviceResponse.Tables(1)) построены с использованием DataSet.ReadXML из результатов веб-сервиса.

Я получил это далеко:

Dim joinedData = From f In localSQLTable _
                 Join s1 As DataRow In serviceResponse.Tables(0) _
                 On f.Item("KNum") Equals s1.Item("Number") _
                 Join s2 As DataRow In serviceResponse.Tables(1) _
                 On s1.Item("KNumber_Id") Equals s2.Item("KNumber_Id") _
                 Select Guid = f.Item("Guid"), Num = f.Item("Num"), Desc = f.Item("Desc"), KNum = f.Item("KNum"), KDesc = s2.Item("KDescription_Text"), Type = s2.Item("Type") _
                 Where (Type.ToString.ToUpper = "LONG_HTML")

myGridView.DataSource = joinedData
myGridView.DataBind()

Однако, казалось, joinedData это просто IEnumerable (анонимного типа). Я пробовал несколько вещей, включая следующие:

  • Попытка построить joinedData как IEnumerable (Of DataRow) с использованием лямбда-функции (о которой я совсем не знаком) для создания нового DataRow
  • Вызов .ToList() или .AsEnumerable() (после игры с типами) в наборе результатов

Основная проблема заключается в том, что независимо от того, что я, похоже, пытаюсь использовать, я использую результаты в качестве источника данных для моего GridView, что-то не так - у меня есть одно из двух исключений:

  • Источник данных для GridView с идентификатором не имеет каких-либо свойств или атрибутов для создания столбцов. Убедитесь, что ваш источник данных имеет содержимое.
  • Источник данных не поддерживает подкачку данных на стороне сервера.

Я также знаю, что, вероятно, не следовало бы использовать .Item ("Field") вместо строго типизированного .Field (Of T)("Field") в моем запросе Linq - я ждал этого изменения, пока не получу данные, пригодные для использования.

Я не женат на Линке; если DataSet.Merge будет более подходящим (или другой методологией), я буду развлекать его. Существует также явная возможность того, что мне придется присоединить то, что у меня есть, к двум другим таблицам данных позже. В таком случае я, скорее всего, объединю таблицы serviceResponse в одну, поэтому я все равно буду объединять только три таблицы.

Итак, что я могу сделать, чтобы объединить эти данные и использовать результат в качестве источника данных моего GridView? И все, что я делаю, будет быстрее, чем просто добавление двух дополнительных столбцов в моей исходной таблице данных (localSQLTable) и заполнение их строка за строкой с использованием данных ответа XML?

Ответы [ 2 ]

2 голосов
/ 08 апреля 2011

В вашем SELECT используйте f.Field<Guid>("Guid") вместо

Пример (C #)

gv.DataSource = serviceResponse.Tables[0].AsEnumerable().Select(r => new { Name = r.Field<Guid>("Guid") });
gv.DataBind();

Пример (vb)

gv.DataSource = dt.AsEnumerable().Select(Function(r) New With { .Name = r.Field(Of Guid)("Guid") })
gv.DataBind()

Или отключить AutoGenerateColumns в GridView

Изменить: Следующий запрос работает нормально

void Main()
{
    var dt1 = new DataTable();
    dt1.Columns.Add("Col1", typeof(string));

    var dt2 = new DataTable();
    dt2.Columns.Add("Col2", typeof(string));

    var row = dt1.NewRow();
    row[0] = "test";
    dt1.Rows.Add(row);

    row = dt2.NewRow();
    row[0] = "test";
    dt2.Rows.Add(row);

    var gv = new GridView();
    gv.DataSource = from t1 in dt1.AsEnumerable()
                    join t2 in dt2.AsEnumerable()
                        on t1[0] equals t2[0]
                    select new
                    {
                        Name1 = t1.Field<string>(0),
                        Name2 = t2.Field<string>(0)
                    };
    gv.DataBind();
}
0 голосов
/ 12 апреля 2011

Конечный результат всего этого следующий:

Dim joinedData As Generic.IEnumerable(Of DataRow) = (From f In localSQLTable.AsEnumerable() _
                                                     Join h In serviceResponse.Tables(0).AsEnumerable() _
                                                     On h.Item("serviceknum") Equals f.Item("knum") _
                                                     Select GetFinalDataRow(finalTable, f, h))

gvGridOne.DataSource = joinedData.CopyToDataTable()
gvGridOne.DataBind()

Я явно определил DataTable и схему (добавив DataColumns) нужного мне конечного DataTable, затем передал этот DataTable и два DataRows в моем объединении в GetFinalDataRow(), определенном как:

Public Function GetFinalDataRow(ByRef FinalTable As DataTable, ByVal Row1 As DataRow, ByVal Row2 As DataRow) As DataRow
    Dim newRow As DataRow = FinalTable.NewRow()
    For Each col As DataColumn In FinalTable.Columns
        If Row1.Table.Columns.Contains(col.ColumnName) Then
            newRow(col.ColumnName) = Row1.Item(col.ColumnName)
        ElseIf Row2.Table.Columns.Contains(col.ColumnName) Then
            newRow(col.ColumnName) = Row2.Item(col.ColumnName)
        Else
            newRow(col.ColumnName) = ""
        End If
    Next

    Return newRow
End Function

Мой объект joinData теперь является IEnumerable из DataRows, и я могу скопировать его в DataTable для источника данных моего GridView, и он будет автоматически генерировать столбцы и разрешать подкачку страниц.

...