Question

Another question. Struggling a little with this SQL stuff.

I am generating 2 tables from queries in ADO.NET. I want to execute a third query from these two tables - that do not exist in the connected database but do exist in the dataset. I can't for the life of me figure out how to do that. I don't want to connect to the database but to the dataset

I've looked at trying DataReaders, TableAdapters, DataTable.Select (which only works for one table) and other things. Does the answer lie in LINQ for Datasets??

Thanks Andy

    Dim strSelect As String
    Dim dsmcmd As OleDbDataAdapter          
    Dim dsm as New DataSet

    strSelect = "TRANSFORM Sum(Items.amount) AS total SELECT Accounts.accCategory, Accounts.ID, Accounts.comment AS Account FROM Accounts INNER JOIN Items ON Accounts.ID = Items.accFrom WHERE (((Year([idate]))=2013) AND ((Items.category)<>3 Or (Items.category) Is Null) AND ((Accounts.accCategory)=6 OR (Accounts.accCategory)=7) AND ((Accounts.curr)=1)) GROUP BY Accounts.accCategory, Accounts.ID, Accounts.comment PIVOT Format(idate,'mmm') IN ('Jan','Feb','Mar','Apr', 'May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')"
    dsmcmd = New OleDbDataAdapter(strSelect, cn)
    dsmcmd.Fill(dsm, "Spent")

    strSelect = "TRANSFORM Sum(Items.amount) AS total SELECT Accounts.accCategory, Accounts.ID, Accounts.comment AS Account FROM Accounts INNER JOIN Items ON Accounts.ID = Items.accFrom WHERE (((Year([idate]))=2013) AND ((Items.category)=3) AND ((Accounts.accCategory)=6) AND ((Accounts.curr)=1)) GROUP BY Accounts.accCategory, Accounts.ID, Accounts.comment PIVOT Format(idate,'mmm') IN ('Jan','Feb','Mar','Apr', 'May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')"
    dsmcmd = New OleDbDataAdapter(strSelect, cn)
    dsmcmd.Fill(dsm, "Allocated")        

    strSelect = "SELECT Totals.accCategory, Totals.ID, Totals.Account, Sum(Totals.Jan) AS Jan FROM (SELECT * FROM Allocated UNION SELECT * FROM Spent) AS Totals GROUP BY Totals.accCategory, Totals.ID, Totals.Account"
    dsmcmd = New OleDbDataAdapter(strSelect, <** WHAT DO I PUT HERE **>)
    dsmcmd.Fill(dsm, "Balance")        
Was it helpful?

Solution

Answer seems to have two parts.

If the DataTables are generated 'in memory' you have to use LINQ

Dim t = (From totals In (allocated.AsEnumerable.Union(spent.AsEnumerable)) _
            Group totals By accCategory = totals.Item("accCategory"), ID = totals.Item("ID"), Account = totals.Item("Account") _
            Into g = Group _
            Select New With {Key .accCategory = accCategory, Key .ID = ID, Key .Account = Account, Key .Jan = g.Sum(Function(totals) If(IsDBNull(totals.Item("Jan")), 0, CDec(totals.Item("Jan"))))}).ToList

You then have to convert it back to a table (if you want to bind it to a DataGrid for example)

Public Function ToTable(Of T)(data As IList(Of T)) As DataTable

    Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
    Dim table As New DataTable()

    For Each prop As PropertyDescriptor In properties
        table.Columns.Add(prop.Name, If(Nullable.GetUnderlyingType(prop.PropertyType), prop.PropertyType))
    Next

    For Each item As T In data
        Dim row As DataRow = table.NewRow()
        For Each prop As PropertyDescriptor In properties
            row(prop.Name) = If(prop.GetValue(item), DBNull.Value)
        Next
        table.Rows.Add(row)
    Next

    Return table

End Function

The only outstanding issue is Null (DBNull) handling - but I'll post a separate question.

Andy

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top