Distinct ComboBox Items - vb.net

I am trying to convert sql to entity and I need to select distinct items. I thought this would work but its returning all the rows instead of the distinct items.
Dim OrderNos = (From r In Orders.R3Delivery Where r.mainOrderNumber <> "" Select r).Distinct().ToList()
For Each thisentry In OrderNos
cbOrderNumbers.DisplayMember = thisentry.mainOrderNumber
cbOrderNumbers.ValueMember = thisentry.mainOrderNumber
Next
Also is their any good free sql to linq tools out their linquer good but its like 60 quid

The problem is that the Distinct() is comparing the entire object being returned, not just the order number.
If you only need the order numbers, changing this line should get you there:
Dim OrderNos = (From r
In Orders.R3Delivery
Where r.mainOrderNumber <> ""
Select r.mainOrderNumber).Distinct().ToList()
If you need the whole object, then it gets more complicated.

Related

How to get the list of non empty queries?

In MS Access I have 1 table that updates daily via external file and 50 queries (named 01_query, 02_query... 50_query), all with same columns and logic but with different filters. Some returns result, others are empty.
How can I get the list (using another query) with the names of NON empty queries?
I found the way to get a list of all query names with this code
SELECT MSysObjects.Name
FROM MsysObjects
WHERE (Left$([Name],1)<>"~") AND (MSysObjects.Type)=5
ORDER BY MSysObjects.Name
but I can't figure out how to filter out the "empty" queries.
If you absolutely must have an Access SQL solution to produce your list, consider something other than UNION of 50 data sources. Access does not allow you to UNION an unlimited number of data sources, but I don't recall what that limit is. And even if it allows you to UNION 50, I still wouldn't do it.
I tested this one in Access 2010 and it produces the result I think you're looking for. Since you've demonstrated you have read permission on MsysObjects it should work for you, too.
SELECT
sub.Name
FROM
(
SELECT
m.Name,
IIf(
m.Name ALike '[0-9][0-9][_]query' AND m.Type=5,
DCount('*', m.Name),
0
) AS non_empty_target_query
FROM MsysObjects AS m
) AS sub
WHERE sub.non_empty_target_query=True
ORDER BY sub.Name;
The IIf() expression is the key to this query. In human-like speak it says, if the object is a query and its name starts with 2 digits followed by an underscore followed by "query", return the count of rows from that query; otherwise just return zero.
Then the parent query filters away those rows where non_empty_target_query is zero (False), leaving only rows containing the names of your "non-empty" queries.
Assuming that all your queries follow the same format, you actually don't need to do anything with MSysObjects. You can just do a simple loop (in VBA):
Public Sub GetNonEmptyQueries()
Dim db As DAO.Database, qdf As DAO.QueryDef
Dim rs As DAO.Recordset
Dim queryName As String
Dim i As Integer
Set db = CurrentDb
For i = 1 To 50
queryName = format(i, "00") & "_query"
Set qdf = db.QueryDefs(format(i, "00") & "_query")
Set rs = qdf.OpenRecordset
If rs.recordCount > 0 Then
' do whatever you need to do with the query name here
Debug.Print qdf.Name
End If
Next i
End Sub
If you don't want to use VBA, it's possible to write a query that UNIONs the COUNT(*) of all your queries. Something like this:
SELECT "01_query" AS QueryName, Count(*) AS [Count] FROM 01_query HAVING COUNT(*) > 0
UNION
SELECT "02_query", COUNT(*) FROM 02_query HAVING count(*) > 0
...
UNION
SELECT "50_query", COUNT(*) FROM 50_query HAVING COUNT(*) > 0
Of course, you're going to have to add all the queries by hand, which is going to get rather tedious. I think the time you would spend hand-writing such a query might be better-spent reading up on VBA, so you can use the first option. :)

LinQ: join on nullable property with value null

I have a list of objects, with a property customerId which is a nullable System.Guid property.
I also have a list of id's of type System.Guid, I also added a Guid.Empty value to this list.
I try to do a join on both, but the objects with empty guids aren't returned.
Dim dos = (From d In documents Join c In allowedCustomers On c Equals If(d.CustomerGuid = Nothing, System.Guid.Empty, d.CustomerGuid) Select d).Skip(10 * (pageNr - 1)).Take(10).ToList
What is wrong? Is there another way to do this in a better way?
You are using d.CustomerGuid = Nothing but you have to use d.CustomerGuid Is Nothing.
Try this approach which uses the VB.NET's null-coalescing operator.
Dim query = From doc In documents
Join custID In allowedCustomers
On If(doc.CustomerGuid, Guid.Empty) Equals custID
Skip 10 * (pageNr - 1)
Take 10
Select doc
Dim docList = query.ToList()
Note that you can increase readability with multiple lines, also, VB.NET's query syntax is powerful than C#, so you can use Skip and Take in the query.

Error when using linq on datatable

I am trying to run the following code converting my datatable to be usable in linq all seems fines and compiles but when I Execute the statement I get the following statement i get the error below new entires just has location and ordernumber in the return values I have to do it this way as I am supporting a legacy access 97 system thanks.
Dim total = From row In newEntries.AsEnumerable()
Select row.Field(Of Int32)("location") Distinct
retVal = Convert.ToInt32(total)
This is my whole code but im still getting an invalid type cast error their is data exsits for this order by teh way
Dim retVal As Int32
Dim newEntries As New DataTable
Dim script As String = scriptBuilder.GetDistinctOrdersForLocations(OrderNumber)
newEntries = connection.SqlSelectToDataTable(script)
Dim total = From row In newEntries.AsEnumerable()
Select row.Field(Of Int32)("location") Distinct
retVal = total.Count()
If you want the count of the collection just do this:
retVal = total.Count()
this will return the count from the distinct query that you have written.
Just to clarify, #David B identified the data type of location was int16 not int32, so changing this in the linq query resolved the issue.
Your LINQ query is returning a collection. You should use something like First or FirstOrDefault.
I'm a little rusty on VB LINQ, but try :
retVal = Convert.ToInt32(total.First())
Note: This will throw an error if there are no items in the collection.
It's important to understand when you write a LINQ query and assign it to a variable, that variable essentially contains a query object, and not the results of running the query. In order to get the value that results from the query, you need to call some method on the query object such as:
total.Single() ' Assumes you expect the query to return exactly one result.
I changed the code to int16 worked here is the code for any one else stuck thanks #Ric
Dim retVal As Int32
Dim newEntries As New DataTable
Dim script As String = scriptBuilder.GetDistinctOrdersForLocations(OrderNumber)
newEntries = connection.SqlSelectToDataTable(script)
Dim total = From row In newEntries.AsEnumerable()
Select row.Field(Of Int16)("location") Distinct
retVal = total.Count()

select count on list using linq on specific value vb.net

I am having an issue getting the results I am looking for. What I need to do is essentially:
Select count(invoicenbr) from invoicelist where invoicenbr = 'invoice'
but when I try it in linq I am not getting the correct results.
When I try to execute the linq query below, it gives me the count for the entire list, and not for the where invoicenbr = 'invoice'...
Here is my linq query that is returning the count for the entire invoiceList:
Dim test = (From invoices In invoicelist _
Where e.Row.Cells("invoicenbr").Value = invoice).count()
You have a naming issue in your code, i assume that it's responsible for your problem.
The variable in your query is invoices but later you use invoice to compare it with the cell value, so you have a different variable in scope with name invoice.
This should work:
Dim invoicenbr As String = e.Row.Cells("invoicenbr").Value
Dim duplicates = From invoice In invoicelist
Where invoice = invoicenbr
Dim duplicateCount As Int32 = duplicates.Count()

DataTable.Select.Where VB.Net - Delete rows

I'm currently pulling information using a query that I'm not allowed to tamper with:
Dim dt As DataTable = BLL.GetData(variable).Tables(0)
Immediately afterwards, I'm removing any records where a field begins with a specific value:
For Each dr As DataRow In dt.Rows
If dr.Item(2).ToString().StartsWith("value") Then
dr.Delete()
End If
Next
What I'd really like to do is something like:
dt.Select.Where(field1 => field1.StartsWith("value")).Delete()
I know that is not the syntax of it and I'm probably very off from what it would be like. The For Each works fine, I'm just trying to "simplify" it. Any idea? Any and all help is appreciated.
Actually, your initial code is probably the cleanest and most straight forward.
To delete items using LINQ, you first need to read them into a separate collection, then loop through that collection and call Delete on each record. If you'd rather go that route, you could try:
Dim records = dt.Rows.Where(Function(r) r.StartsWith("value")).ToList()
For Each r In records
r.Delete()
Next
The answer I think you are looking for is below from Microsoft. https://msdn.microsoft.com/en-us/library/det4aw50(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
Dim table As DataTable = DataSet1.Tables("Orders")
' Presuming the DataTable has a column named Date.
Dim expression As String
expression = "Date > #1/1/00#"
Dim foundRows() As DataRow
' Use the Select method to find all rows matching the filter.
foundRows = table.Select(expression)
Dim i As Integer
' Print column 0 of each returned row.
For i = 0 to foundRows.GetUpperBound(0)
Console.WriteLine(foundRows(i)(0))
Next i