2011-04-07 57 views
2

我有三个DataTable需要连接在一起,并使用连接的数据作为GridView的DataSource。第一个(localSQLTable)通过针对MS-SQL数据库的查询进行填充。后两个(serviceResponse.Tables(0)serviceResponse.Tables(1))是使用DataSet.ReadXML从Web服务的结果构建的。LINQ to DataSet - 连接和GridView问题

我这个地步得到:

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函数(我是其中不熟悉的话)来建立新的DataRow试图建立joinedData作为一个IEnumerable(中的DataRow)
  • 调用.ToList().AsEnumerable()的结果(与类型玩弄后)设置

的主要问题是,不管什么我似乎尝试,有一些错误使用结果作为数据源为我的GridView的 - 我两个例外之一:

  • 带ID的GridView的数据源没有任何要从中生成列的属性或属性。确保您的数据源包含内容。
  • 数据源不支持服务器端数据分页。

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

我没有和Linq结婚;如果DataSet.Merge更合适(或其他一些方法),我会招待它。还有一种明显的可能性,那就是我实际上不得不在晚些时候加入其他两个DataTable。如果是这样的话,我可能会将serviceResponse表合并为一个,所以我仍然只能加入三张表。

那么我能做些什么来将这些数据结合在一起并将结果用作我的GridView的DataSource?而且我所做的任何事情都会比在我的原始DataTable(localSQLTable)中添加两个额外列并使用XML响应数据逐行填充它们更快?

回答

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

我明确定义的数据表和模式(通过添加DataColumns)则结束数据表,我需要的,然后通过了DataTable,并在我的两个数据行加入到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Ø f DataRows,我可以将它复制到我的GridView数据源的DataTable中,并且它会自动生成列并允许分页。

2

在你选择使用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(); 
} 
+0

对不起等待。我很乐意保持AutoGenerateColumns的真实性 - 我会尽快尝试并回复您。 – 2011-04-08 20:26:54

+0

没有工作 - 看起来像一个铸造问题,就像我需要明确选择数据行,也许。我收到以下内容: '无法将类型为<<可怕的长字符串的对象称为匿名类型'来键入'System.Collections.Generic.IEnumerable'1 [System.Data.DataRow]'。' – 2011-04-11 15:23:49

+0

'在表上添加AsEnumerable()? – Magnus 2011-04-11 15:43:04