LINQ to DataSet - 联接和GridView问题

时间:2011-04-07 21:17:37

标签: .net asp.net vb.net linq linq-to-dataset

我有三个DataTable需要连接在一起,并使用连接数据作为GridView的DataSource。第一个(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(匿名类型)。我尝试了一些事情,包括以下内容:

  • 尝试使用lambda函数(我根本不熟悉)将joinedData构建为IEnumerable(Of DataRow)来构建新的DataRow
  • 在结果集上调用.ToList().AsEnumerable()(在玩弄类型后)

主要问题是,无论我多么尝试,将结果用作GridView的DataSource都有问题 - 我得到了两个例外之一:

  • 具有id的GridView的数据源没有用于生成列的任何属性或属性。确保您的数据源包含内容。
  • 数据源不支持服务器端数据分页。

我也知道我可能不应该在我的Linq查询中使用.Item ("Field")而不是强类型.Field (Of T)("Field") - 我等待这个更改,直到我得到实际可用的数据。

我没和Linq结婚;如果DataSet.Merge更合适(或其他方法),我会接受它。还有一个明显的可能性,我实际上必须加入我以后的另外两个DataTables。如果是这种情况,我可能会将serviceResponse表合并为一个,所以我仍然只会加入三个表。

那么我该怎样做才能将这些数据连接在一起并将结果用作我的GridView的DataSource?我正在做的任何事情都要比在我的原始DataTable(localSQLTable)中添加两个额外的列并使用XML响应数据逐行填充它们更快?

2 个答案:

答案 0 :(得分:2)

在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()

或在GridView上禁用AutoGenerateColumns

修改 以下查询工作正常

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();
}

答案 1 :(得分:0)

所有这一切的最终结果如下:

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的DataTable和模式(通过添加DataColumns),然后将我的连接中的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

我的joinedData对象现在是一个IEnumerable的DataRows,我可以将它复制到我的GridView数据源的DataTable中,它会自动生成列并允许分页。