<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Code Corner &#187; ADO.NET</title>
	<atom:link href="http://CodeCorner.galanter.net/category/vbnet/adonet/feed/" rel="self" type="application/rss+xml" />
	<link>http://CodeCorner.galanter.net</link>
	<description>ASP.NET, XML, SQL and Javascript tips and tricks</description>
	<lastBuildDate>Sun, 19 Feb 2012 03:04:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>WHDG: RowIslandsPopulating event fires multiple times</title>
		<link>http://CodeCorner.galanter.net/2011/10/28/whdg-rowislandspopulating-event-fires-multiple-times/</link>
		<comments>http://CodeCorner.galanter.net/2011/10/28/whdg-rowislandspopulating-event-fires-multiple-times/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 16:31:09 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Infragistics]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[solution]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=1457</guid>
		<description><![CDATA[I&#8217;ve been successfully using manual load on demand in WebHierarchicalDataGrid for a while now, but recently noticed strange thing. The deeper in grid&#8217;s hierarchy I expanded the children &#8211; the slower it went. In my case every time user clicks [+] to expand a row, VB.NET code calls an SQL Server Stored procedure to bring [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been successfully using <a href="http://codecorner.galanter.net/2010/12/23/webhierarchicaldatagrid-manual-load-on-demand-when-bound-to-dataset/">manual load on demand in WebHierarchicalDataGrid</a> for a while now, but recently noticed strange thing. The deeper in grid&#8217;s hierarchy I expanded the children &#8211; the slower it went.</p>
<p>In my case every time user clicks [+] to expand a row, VB.NET code calls an SQL Server Stored procedure to bring in child rows. I grew suspicious and fired up SQL Profiler. What I saw surprised me. Number of calls to the stored procedure increased the deeper in grid&#8217;s hierarchy I expanded the children. When I clicked [+] on the root level it resulted in 1 SP call. Clicking [+] on the child to expand grandchild &#8211; 2 calls. Expanding grandchild to see grand-grandchild rows &#8211; 3 calls, etc.<span id="more-1457"></span></p>
<p>I went back to the VB.NET code that calls the SP, it&#8217;s the handler for <em>RowIslandsPopulating</em> event:</p>
<pre class="brush: vb; title: ; notranslate"> Protected Sub xmyGrid_RowIslandsPopulating(ByVal sender As Object, _
ByVal e As ContainerRowCancelEventArgs) Handles xmyGrid.RowIslandsPopulating

   e.Cancel = True
   CreateRowIslands(e.Row)

End Sub</pre>
<p>Where <em>CreateRowIslands</em> is a VB sub that calls SQL Server Stored procedure to create child grid. Setting a breakpoint here I confirmed my suspicions: <em>RowIslandsPopulating</em> event is called for rows that already have been expanded. E.g. if I expand grand-child to display grand-grand-child rows, the event will fire for root, child and grand-child &#8211; 3 times, in turn calling stored procedure 3 times.</p>
<p>How to avoid this? While comparing the multiple calls I realized that rows already expanded had their <em>Expanded</em> property set to <em>True</em>. And while we can prevent <em>RowIslandsPopulating</em> event from firing multiple times, we can at least tell it not to do anything if RowIslands are already populated. So, the very slight change:</p>
<pre class="brush: vb; title: ; notranslate"> Protected Sub xmyGrid_RowIslandsPopulating(ByVal sender As Object, _
ByVal e As ContainerRowCancelEventArgs) Handles xmyGrid.RowIslandsPopulating

   e.Cancel = True
   If e.Row.Expanded = False CreateRowIslands(e.Row)

End Sub</pre>
<p>Solves the issue.</p>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2010/12/23/webhierarchicaldatagrid-manual-load-on-demand-when-bound-to-dataset/" rel="bookmark" class="crp_title">WebHierarchicalDataGrid: Manual Load on Demand when bound to DataSet</a></li><li><a href="http://CodeCorner.galanter.net/2008/09/26/ultrawebgrid-in-outlookgroupby-mode-how-to-count-total-number-of-rows-in-a-subgroup/" rel="bookmark" class="crp_title">UltraWebGrid in OutlookGroupBy Mode: How to count total number of rows in subgroups</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2011/10/28/whdg-rowislandspopulating-event-fires-multiple-times/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server stored procedure runs slow from .NET code</title>
		<link>http://CodeCorner.galanter.net/2011/08/05/sql-server-stored-procedure-runs-slow-from-net-code/</link>
		<comments>http://CodeCorner.galanter.net/2011/08/05/sql-server-stored-procedure-runs-slow-from-net-code/#comments</comments>
		<pubDate>Fri, 05 Aug 2011 18:58:54 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[slow]]></category>
		<category><![CDATA[solution]]></category>
		<category><![CDATA[speed]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=1365</guid>
		<description><![CDATA[This has probably been discussed a lot before, but just in case here it is again, possible solution for following scenario: You&#8217;re calling SQL Server stored procedure from your .NET code and it runs extremely slow. When you run same SP with exactly the same parameters (as captured by SQL Server Profiler) directly in SQL [...]]]></description>
			<content:encoded><![CDATA[<p>This has probably been discussed a lot before, but just in case here it is again, possible solution for following scenario:</p>
<p><em>You&#8217;re calling SQL Server stored procedure from your .NET code and it runs extremely slow. When you run same SP with exactly the same parameters (as captured by SQL Server Profiler) directly in SQL Server Management Studio, it runs very fast. What gives?</em></p>
<p>Chances are &#8211; that SP was executed before and query plan was cached for the specific parameters. To avoid this add <strong>WITH RECOMPILE</strong> option to your <strong>CREATE PROCEDURE</strong> or <strong>ALTER PROCEDURE</strong> statement. This will force SQL Server to create a new query plan every time SP runs, perhaps adding slight overhead, but creating an optimized path that will cover that overhead tenfold.</p>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2011/04/29/ssrs-how-to-implement-build-in-parameter-based-on-external-parameter-passed-from-reportviewer/" rel="bookmark" class="crp_title">SSRS: How to implement build-in parameter based on external parameter passed from ReportViewer</a></li><li><a href="http://CodeCorner.galanter.net/2011/06/14/stored-procedure-in-linq2sql-query/" rel="bookmark" class="crp_title">Stored Procedure in LINQ2SQL query</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2011/08/05/sql-server-stored-procedure-runs-slow-from-net-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cheat for &#8220;These columns don&#8217;t currently have unique values&#8221; error</title>
		<link>http://CodeCorner.galanter.net/2011/02/22/cheat-for-dataset-datarelations/</link>
		<comments>http://CodeCorner.galanter.net/2011/02/22/cheat-for-dataset-datarelations/#comments</comments>
		<pubDate>Tue, 22 Feb 2011 16:20:05 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=1164</guid>
		<description><![CDATA[Ordinary when you create a parent-child relationship between DataTables in a DataSet &#8211; there is a requirement that all values of the parent columns need to be unique. If they&#8217;re not &#8211; you will get an error: &#8220;These columns don&#8217;t currently have unique values&#8220;. But there&#8217;re times when you need to make the relationship work [...]]]></description>
			<content:encoded><![CDATA[<p>Ordinary when you create a parent-child relationship between DataTables in a DataSet &#8211; there is a requirement that all values of the parent columns need to be unique. If they&#8217;re not &#8211; you will get an error: &#8220;<em>These columns don&#8217;t currently have unique values</em>&#8220;.</p>
<p>But there&#8217;re times when you need to make the relationship work even if those values are not unique. The solution is <em>not to create constrain</em> when creating the relationship. This can be done for example by passing <em>FALSE</em> as value for <strong>createConstrains</strong> parameter of <strong>Dataset.Relations.Add</strong> method:</p>
<pre class="brush: vb; highlight: [4]; title: ; notranslate">oMyDataSet.Relations.Add(&quot;MyRel&quot;, _
oMyDataSet.Tables(&quot;TheParent&quot;).Columns(&quot;ParentColumn&quot;), _
dtSet.Tables(&quot;TheChild&quot;).Columns(&quot;ChildColumn&quot;), _
False)</pre>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2010/12/23/webhierarchicaldatagrid-manual-load-on-demand-when-bound-to-dataset/" rel="bookmark" class="crp_title">WebHierarchicalDataGrid: Manual Load on Demand when bound to DataSet</a></li><li><a href="http://CodeCorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/" rel="bookmark" class="crp_title">Group By and Aggregates in .NET DataTable</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2011/02/22/cheat-for-dataset-datarelations/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WebHierarchicalDataGrid: Manual Load on Demand when bound to DataSet</title>
		<link>http://CodeCorner.galanter.net/2010/12/23/webhierarchicaldatagrid-manual-load-on-demand-when-bound-to-dataset/</link>
		<comments>http://CodeCorner.galanter.net/2010/12/23/webhierarchicaldatagrid-manual-load-on-demand-when-bound-to-dataset/#comments</comments>
		<pubDate>Thu, 23 Dec 2010 15:59:13 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[Infragistics]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[solution]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=1110</guid>
		<description><![CDATA[Even though I have my issues with Infragistics WebHierarchicalDataGrid control, it has some neat features and I found that with some tweaks you can make it work. Case in point: Manual Load on Demand. If you have hierarchical data structure, it allows you to retrieve only root level data and then when user clicks &#8220;Expand&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>Even though I have my <a href="http://codecorner.galanter.net/2010/10/21/webhierarchicaldatagrid-not-ready-for-primetime/">issues</a> with Infragistics WebHierarchicalDataGrid control, it has some neat features and I found that with some tweaks you can make it work.</p>
<p>Case in point: Manual Load on Demand. If you have hierarchical data structure, it allows you to retrieve only root level data and then when user clicks &#8220;Expand&#8221; arrow &#8211; get additional data on as needed basis:</p>
<p><img src="http://www.galanter.net/sitepic/mlod1.png" alt="Manual Load on Demand in action" /></p>
<p>This is achieved by handling <strong>RowIslandsPopulating</strong> grid&#8217;s event in which you can run a DB query based on parent row data, then manually create a<strong> ContainerGrid</strong> object bind it to the data and add it to parent row <strong>RowIslands</strong> collection:</p>
<pre class="brush: vb; title: ; notranslate">Protected Sub myGrid_RowIslandsPopulating(ByVal sender As Object, ByVal e As ContainerRowCancelEventArgs) Handles myGrid_.RowIslandsPopulating

     e.Cancel = True

     Dim oData as SomeDataType = GetData()
     Dim oChildGrid As New ContainerGrid()

     e.Row.RowIslands.Add(oChildGrid)

     oChildGrid.DataKeyFields = &quot;SOME_ID&quot;
     oChildGrid.Level = e.Row.Level + 1
     oChildGrid.DataSource = oData
     oChildGrid.DataBind()

End Sub</pre>
<p>For this approach to work top-level rows need to display &#8220;Expand&#8221; arrows that user can click.<span id="more-1110"></span> This is done by looping thru all top-level rows in grid&#8217;s <strong>PreRender</strong> event, setting each row&#8217;s <strong>IsEmptyParent</strong> property to true:</p>
<pre class="brush: vb; title: ; notranslate">Protected Sub myGrid_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles myGrid.PreRender

    If myGrid.DataSource IsNot Nothing Then
        For Each oRow As ContainerGridRecord In myGrid.GridView.Rows
            Row.IsEmptyParent = True
        Next
    End If

End Sub</pre>
<p>This should work, but unfortunately if your source for the root level grid is DataSet &#8211; it doesn&#8217;t. </p>
<p><img src="http://www.galanter.net/sitepic/mlod2.png" alt="Expand arrows aren't rendered" /></p>
<p>The reason &#8211; WebHierarchicalDataGrid expects hierarchy in the data source and if DataSet has a single table and no relationship &#8211; the &#8220;Expand&#8221; arrows will never be rendered. So we have to fake it (Great minds think alike, I found this solution in the same time it was suggested by Infragistics support). Once your root DataSet is filled with data, add following code:</p>
<pre class="brush: vb; title: ; notranslate">oMyDataSet.Tables.Add()
oMyDataSet.Tables(1).Columns.Add(&quot;MY_ID&quot;, GetType(Integer))
oMyDataSet.Relations.Add(oMyDataSet.Tables(0).Columns(&quot;MY_ID&quot;), oMyDataSet.Tables(1).Columns(&quot;MY_ID&quot;))</pre>
<p>Just substituted &#8220;MY_ID&#8221; with some real column ID from your root table. The code will create fake relationship letting grid to render &#8220;Expand&#8221; arrows when running code from above in PreRender event.</p>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2011/10/28/whdg-rowislandspopulating-event-fires-multiple-times/" rel="bookmark" class="crp_title">WHDG: RowIslandsPopulating event fires multiple times</a></li><li><a href="http://CodeCorner.galanter.net/2011/02/22/cheat-for-dataset-datarelations/" rel="bookmark" class="crp_title">Cheat for &#8220;These columns don&#8217;t currently have unique values&#8221; error</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2010/12/23/webhierarchicaldatagrid-manual-load-on-demand-when-bound-to-dataset/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Cannot find column&#8221; DataTable error while grouping or sorting Infragistics UltraWebGrid</title>
		<link>http://CodeCorner.galanter.net/2010/05/28/cannot-find-column-datatable-error/</link>
		<comments>http://CodeCorner.galanter.net/2010/05/28/cannot-find-column-datatable-error/#comments</comments>
		<pubDate>Fri, 28 May 2010 16:08:50 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[Infragistics]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[Error]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[trick]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=954</guid>
		<description><![CDATA[If you&#8217;re binding an ADO.NET DataTable to Infragistics UltraWebGrid and then programmaticaly sort the grid (e.g. add a column to a band&#8217;s SortedColumns collection) you may get an error: Cannot find column My Column Name. with stack trace starting from grid databinding and finishing in datatable&#8217;s sorting: at System.Data.DataTable.ParseSortString(String sortString) at System.Data.DataView.CheckSort(String sort) at System.Data.DataView.set_Sort(String [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re binding an ADO.NET DataTable to Infragistics UltraWebGrid and then programmaticaly sort the grid (e.g. add a column to a band&#8217;s SortedColumns collection) you may get an error:</p>
<p><span style="color: #ff0000;">Cannot find column My Column Name.</span></p>
<p>with stack trace starting from grid databinding and finishing in datatable&#8217;s sorting:</p>
<p><span style="color: #ff0000;">at System.Data.DataTable.ParseSortString(String sortString)<br />
at System.Data.DataView.CheckSort(String sort)<br />
at System.Data.DataView.set_Sort(String value)<br />
at Infragistics.WebUI.UltraWebGrid.DBBinding.ProcessDataViewForFillRows(DataView dataView, RowsCollection rows)<br />
at Infragistics.WebUI.UltraWebGrid.DBBinding.FillRows(UltraWebGrid grid, RowsCollection rows, IEnumerable datasource)<br />
at Infragistics.WebUI.UltraWebGrid.DBBinding.BindList(IEnumerable datasource)<br />
at Infragistics.WebUI.UltraWebGrid.DBBinding.DataBind(Object dataSource, String dataMember)<br />
at Infragistics.WebUI.UltraWebGrid.UltraWebGrid.DataBind() </span></p>
<p>If the grid binds OK without sorting and grouping, but fails with either &#8211; most likely the culprit is one of the columns in data table.<span id="more-954"></span> Sort expression passed to a DataView is a comma separated list of column names to sort by. So, if your column name has a comma in it e.g. &#8220;My Column Name, For Real&#8221; &#8211; this presents a problem, since DataView will try to sort by 2 non-existing columns &#8220;My Column Name&#8221; (hence the error above) and &#8220;For Real&#8221;.</p>
<p>One way to deal with the problem is replace the comma with comma-like character &#8220;¸&#8221; called Cedilla (keystroke Alt+0184). So if after data retrieval you insert a loop like this:</p>
<pre class="brush: vb; title: ; notranslate">'dtData is a data table already populated with data
For Each oCol As DataColumn In dtData.Columns
    oCol.ColumnName = oCol.ColumnName.Replace(&quot;,&quot;, &quot;¸&quot;)
Next</pre>
<p>then the sorting will perform correctly and without errors, and comma-like appearance will be preserved in column name.</p>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2010/04/12/showing-all-filters-in-ultrawebgrid-with-paging/" rel="bookmark" class="crp_title">Showing ALL filters in UltraWebGrid with paging</a></li><li><a href="http://CodeCorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/" rel="bookmark" class="crp_title">Group By and Aggregates in .NET DataTable</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2010/05/28/cannot-find-column-datatable-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using LINQ to bind flat data to Infragistics UltraWebTree</title>
		<link>http://CodeCorner.galanter.net/2010/01/10/using-linq-to-bind-flat-data-to-infragistics-ultrawebtree/</link>
		<comments>http://CodeCorner.galanter.net/2010/01/10/using-linq-to-bind-flat-data-to-infragistics-ultrawebtree/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 04:37:35 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Infragistics]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[linq]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=842</guid>
		<description><![CDATA[Often you have to operate with flattened data that in reality contains multiple levels of hierarchy. For example it can come as a result of several SQL JOIN statement and look like this: In this example data consist of static root column, region, site, type and state. And the data has clearly defined hierarchy (e.g. [...]]]></description>
			<content:encoded><![CDATA[<p>Often you have to operate with flattened data that in reality contains multiple levels of hierarchy. For example it can come as a result of several SQL JOIN statement and look like this:</p>
<p><img src="http://www.galanter.net/sitepic/FlatData.png" alt="" /></p>
<p>In this example data consist of static root column, region, site, type and state. And the data has clearly defined hierarchy (e.g. Region &#8220;India&#8221; has site &#8220;Bangalore&#8221;, site &#8220;Bangalore&#8221; has types &#8220;Application&#8221; and &#8220;Area&#8221;, type &#8220;Application&#8221; has states &#8220;N/A&#8221; and &#8220;Testing&#8221;).</p>
<p>To load this data into Infragistics UltraWebTree I put together a small procedure:<span id="more-842"></span></p>
<pre class="brush: vb; title: ; notranslate">Sub PopulateNavigatorTree(ByVal i_dtTable As DataTable, ByVal i_aNodes As Nodes, ByVal i_iGroupNo As Integer, ByVal i_sFilter As String)

    Dim oNode As Node

    Dim aFilteredData = From row As DataRow In i_dtTable _
          Where row.Field(Of String)(i_iGroupNo - 1) = i_sFilter _
          Select row

    Dim aQuery = From row In aFilteredData _
          Select row.Field(Of String)(i_iGroupNo) Distinct

    For Each sGrName As String In aQuery
         oNode = i_aNodes.Add(sGrName)

         If i_iGroupNo &lt; i_dtTable.Columns.Count - 1 Then
              PopulateNavigatorTree(aFilteredData.CopyToDataTable, oNode.Nodes, i_iGroupNo + 1, sGrName)
         End If

    Next

End Sub</pre>
<p>As parameters it accepts DataTable with flat data, collection of tree nodes (initially empty), group number (or column number in the table) and field data as a filter. So using data example from above and data table named <em>dtData</em> and tree named <em>xuwtTree</em> the call to the function will be:</p>
<pre class="brush: vb; title: ; notranslate">PopulateNavigatorTree(dtData, xuwtTree.Nodes, 1, &quot;GR&quot;)</pre>
<p>First LINQ query (<em>Lines 5-7</em>) selects only those DataRows from the DataTable that belong to hierarchy of one level above current (using input parameter as a filter). The second query (<em>lines 9-10</em>) selects distinct field names from the current level. Then the loop (<em>Lines 12-19</em>) iterates thru those names, adding them to tree node collection (<em>Line 13</em>). And if there&#8217;re more groups to process (table has more columns) function calls itself recursively (<em>Lines 15-17</em>), passing filtered data, created by LINQ query previously and now converted back to data table,  child Nodes collection of newly created node (currently empty), column number incremented by 1 and current field data as filter. The result:</p>
<p><img src="http://www.galanter.net/sitepic/TreeData.png" alt="" /></p>
<p>This approach assumes that there is on common root element (&#8220;GR&#8221; in this case) in the flat data and uses Infragistics UltraWebTree as target control, but it can easly be adapted to other scenarios and controls.</p>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2010/04/12/showing-all-filters-in-ultrawebgrid-with-paging/" rel="bookmark" class="crp_title">Showing ALL filters in UltraWebGrid with paging</a></li><li><a href="http://CodeCorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/" rel="bookmark" class="crp_title">Group By and Aggregates in .NET DataTable</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2010/01/10/using-linq-to-bind-flat-data-to-infragistics-ultrawebtree/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>LINQ: Truly language integrated. Using VB functions inside of LINQ Query</title>
		<link>http://CodeCorner.galanter.net/2009/12/17/linq-truly-language-integrated/</link>
		<comments>http://CodeCorner.galanter.net/2009/12/17/linq-truly-language-integrated/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 22:15:08 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[cool]]></category>
		<category><![CDATA[linq]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=746</guid>
		<description><![CDATA[LINQ is truly integrated into VB.NET. This allows not only to use LINQ-specific query language in a standard VB.NET code, but use VB.NET code in a LINQ query. Consider function from the previous post. To make it universal we can pass one more parameter &#8220;Aggregate Type&#8221; and based on that parameter return Min, Max, Avg, [...]]]></description>
			<content:encoded><![CDATA[<p>LINQ is truly integrated into VB.NET. This allows not only to use LINQ-specific query language in a standard VB.NET code, but use VB.NET code in a LINQ query. Consider <a href="http://codecorner.galanter.net/2009/12/17/grouping-ado-net-datatable-using-linq/">function from the previous post</a>. To make it universal we can pass one more parameter<br />
&#8220;Aggregate Type&#8221; and based on that parameter return Min, Max, Avg, Sum or Count</p>
<pre class="brush: vb; title: ; notranslate">Function GroupBy(ByVal i_sGroupByColumn As String,  ByVal i_sAggregateColumn As String, ByVal i_dSourceTable As DataTable, i_iAggregateType as Integer) As DataTable

     dim aQuery = From row In i_dSourceTable Group By Group1 = row(i_sGroupByColumn) Into Group Select Group1,  Aggr = Choose(i_iAggregateType, Group.Min(Function(row) row(i_sAggregateColumn)), Group.Max(Function(row) row(i_sAggregateColumn)), Group.Sum(Function(row) row(i_sAggregateColumn)), Group.Avg(Function(row) row(i_sAggregateColumn)), Group.Count(Function(row) row(i_sAggregateColumn)))

    return aQuery.toDataTable

End Function</pre>
<p>In this example VB.NET function <em>Choose</em> is used inside of a LINQ query&#8217;s <em>Select</em> Statement. If <em>i_iAggregateType</em> parameter is equal 1 &#8211; Minimum value, will be calculated, 2 &#8211; Maximum etc.</p>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2009/12/17/grouping-ado-net-datatable-using-linq/" rel="bookmark" class="crp_title">Grouping ADO.NET DataTable using LINQ</a></li><li><a href="http://CodeCorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/" rel="bookmark" class="crp_title">Group By and Aggregates in .NET DataTable</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2009/12/17/linq-truly-language-integrated/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grouping ADO.NET DataTable using LINQ</title>
		<link>http://CodeCorner.galanter.net/2009/12/17/grouping-ado-net-datatable-using-linq/</link>
		<comments>http://CodeCorner.galanter.net/2009/12/17/grouping-ado-net-datatable-using-linq/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 15:22:16 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[cool]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[linq]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=725</guid>
		<description><![CDATA[I&#8217;ve described before how to group and aggregate data in ADO.NET data table using standard .NET 2.0 features. But if you happen to use .NET 3.5 or above and Visual Studio 2008 or above &#8211; that entire block of code can be replaced with a single LINQ query: The query at line 3 is a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve described before <a href="http://codecorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/">how to group and aggregate data in ADO.NET data table using standard .NET 2.0 features</a>. But if you happen to use .NET 3.5 or above and Visual Studio 2008 or above &#8211; that entire block of code can be replaced with a single LINQ query:</p>
<pre class="brush: vb; title: ; notranslate">Function GroupBy(ByVal i_sGroupByColumn As String,  ByVal i_sAggregateColumn As String, ByVal i_dSourceTable As DataTable) As DataTable

     dim aQuery = From row In i_dSourceTable Group By Group1 = row(i_sGroupByColumn) Into Group Select Group1,  Aggr = Group.Count(Function(row) row(i_sAggregateColumn))

    return aQuery.toDataTable

End Function</pre>
<p>The query at line 3 is a <em>LINQ to DataSet</em> query, so reference to <em>System.Data.Linq</em> has to be added to your project. The <em>Group.Count</em> aggregate can be replaced with Group.Max, Group.Min, Group.Sum or Group.Avg to perform respectful function.</p>
<p>There is one caveat though.<span id="more-725"></span> If you need to return grouped result as a data table, a <em>.toDataTable</em> method needs to be used on query results. Unfortunately this method exists only if your query is of a type <em>IEnumerable(of DataRow)</em> in other words returns datarows. The query above returns anonymous type. So there is no ready-to-use <em>.toDataTable</em> method.</p>
<p>Fortunately the method can be added. Download following 2 code modules (borrowed from the code accompanied &#8220;LINQ in Action book):</p>
<p><a href="http://kitchen.galanter.net/sitepic/ObjectShreder.zip">ObjectShreder.vb</a><br />
<a href="http://kitchen.galanter.net/sitepic/DataSetLinqOperators.zip">DataSetLinqOperators.vb</a></p>
<p>Add them to your project. Bingo! Your query of a type <em>IEnumerable(of &lt;anonymous type&gt;)</em> now has <em>.toDataTable</em> method.</p>
<p>Another possibility (if you don&#8217;t want to use some external 3-rd party code) is to build a table the standard way creating and filling table rows while looping thru query results.</p>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2009/12/17/linq-truly-language-integrated/" rel="bookmark" class="crp_title">LINQ: Truly language integrated. Using VB functions inside of LINQ Query</a></li><li><a href="http://CodeCorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/" rel="bookmark" class="crp_title">Group By and Aggregates in .NET DataTable</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2009/12/17/grouping-ado-net-datatable-using-linq/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Group By and Aggregates in .NET DataTable</title>
		<link>http://CodeCorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/</link>
		<comments>http://CodeCorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 13:31:14 +0000</pubDate>
		<dc:creator>Yuriy</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[VB.NET]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">http://CodeCorner.galanter.net/?p=161</guid>
		<description><![CDATA[Often there is a need to perform group by operations on in-memory .NET data tables. You can’t run a standard SQL statement and LINQ is not available prior version 3.0 of .NET. To compensate for this shortcoming I put together a small function that works in .NET 2.0. As input parameters it accepts source DataTable, [...]]]></description>
			<content:encoded><![CDATA[<p>Often there is a need to perform group by operations on in-memory .NET data tables. You can’t run a standard SQL statement and LINQ is not available prior version 3.0 of .NET. To compensate for this shortcoming I put together a small function that works in .NET 2.0. As input parameters it accepts source DataTable, column name to group by and a column name to perform aggregate operation on. It returns a grouped data as data table:</p>
<pre class="brush: vb; title: ; notranslate">Function GroupBy(ByVal i_sGroupByColumn As String, ByVal i_sAggregateColumn As String, ByVal i_dSourceTable As DataTable) As DataTable

        Dim dv As New DataView(i_dSourceTable)

        'getting distinct values for group column
        Dim dtGroup As DataTable = dv.ToTable(True, New String() {i_sGroupByColumn}) 

        'adding column for the row count
        dtGroup.Columns.Add(&quot;Count&quot;, GetType(Integer)) 

        'looping thru distinct values for the group, counting
        For Each dr As DataRow In dtGroup.Rows
            dr(&quot;Count&quot;) = i_dSourceTable.Compute(&quot;Count(&quot; &amp; i_sAggregateColumn &amp; &quot;)&quot;, i_sGroupByColumn &amp; &quot; = '&quot; &amp; dr(i_sGroupByColumn) &amp; &quot;'&quot;)
        Next        

        'returning grouped/counted result
        Return dtGroup
End Function</pre>
<p>The function first gets distinct values for group-by column, by creating a data view from source data table and using DataView’s &#8220;ToTable&#8221; method. It then loops thru these distinct values performing aggregate function on the source table using DataTable’s &#8220;Compute&#8221; method &#8211; Count in this case, but it can easily be replaced with other aggregates.</p>
<div id="crp_related"><h4>Related Posts:</h4><ul><li><a href="http://CodeCorner.galanter.net/2009/12/17/grouping-ado-net-datatable-using-linq/" rel="bookmark" class="crp_title">Grouping ADO.NET DataTable using LINQ</a></li><li><a href="http://CodeCorner.galanter.net/2009/12/17/linq-truly-language-integrated/" rel="bookmark" class="crp_title">LINQ: Truly language integrated. Using VB functions inside of LINQ Query</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://CodeCorner.galanter.net/2009/04/20/group-by-and-aggregates-in-net-datatable/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
	</channel>
</rss>

