Multiple Dynamic Order By in Linq to Entity Framework - vb.net

Dim receipts As IQueryable(Of ReceiptEntity) = db.Receipts
'code to filter removed for brevity
Dim sorts() As String = SortExpression.Split(";")
For Each sort As String In sorts
Dim sortParts() As String = sort.Split(" ")
If sortParts(1).ToLower = "true" Then
receipts = receipts.OrderBy(Of ReceiptEntity)(sortParts(0).ToString(), SortDirection.Ascending)
Else
receipts = receipts.OrderBy(Of ReceiptEntity)(sortParts(0).ToString(), SortDirection.Descending)
End If
Next
SortExpression comes in like "field1 true;field2 false;field3 true"
What I want to happen is for the query to have multiple order by fields, what is happening is that only the last order by is applied. What am I doing wrong here?
Here is what the working result looks like:
Dim receipts As IOrderedQueryable(Of ReceiptEntity) = db.Receipts.Include(Function(r) r.LineItems).Include(Function(r) r.Payments)
Dim sorts() As String = SortExpression.Split(";")
Dim sortParts() As String
sortParts = sorts(0).Split(" ")
If sortParts(1).ToLower = "true" Then
receipts = receipts.OrderBy(sortParts(0).ToString())
Else
receipts = receipts.OrderByDescending(sortParts(0).ToString())
End If
For Each sort As String In sorts.Skip(1)
sortParts = sort.Split(" ")
If sortParts(1).ToLower = "true" Then
receipts = receipts.ThenBy(sortParts(0).ToString())
Else
receipts = receipts.ThenByDescending(sortParts(0).ToString())
End If
Next

You have to use ThenBy instead of OrderBy for the second and all subsequent sort operations.

Related

Remove Duplicate Objects from list in VB.Net

I am trying to remove duplicate object from a list based on the companyID.
How do I integrate through a list and remove the object based on a companyID.
While reader.Read()
companys.Add(New CompanySearch)
companys(companys.Count - 1).StartDate = reader("StartDate").ToString & " (" & count & ")"
companys(companys.Count - 1).CompanyID = reader("company").ToString
companys(companys.Count - 1).Origin = reader("Origin").ToString
companys(companys.Count - 1).OriginName = reader("OriginName").ToString
companys(companys.Count - 1).Status = reader("status").ToString
companys(companys.Count - 1).StatusName = reader("statusname").ToString
companys(companys.Count - 1).Status = reader("status").ToString
companys(companys.Count - 1).FullLegalBusinessName = reader("fullLegalBusinessName")
companys(companys.Count - 1).AmountRequestedText = reader("amountRequestedText")
companys(companys.Count - 1).HowSoonNeededText = reader("howSoonNeededText")
companys(companys.Count - 1).QueueID = reader("QueueID")
companys(companys.Count - 1).Company = reader("Company")
End While
For counter As Integer = 0 To companys.Count
counter += 1
If i <> CInt(companys(companys.Count - 1).CompanyID) Then
i = CInt(companys(companys.Count - 1).CompanyID)
Else
companys.Remove()
End If
Next
Don't add them in the first place. Use either aDictionary (if you will look them up by ID later) or a HashSet (if you won't) to check before adding to the results. Here's the HashSet example:
Dim companyIDs As New HashSet(Of String)()
While reader.Read()
If Not companyIDs.Contains(reader("company").ToString()) Then
companys.Add(New CompanySearch() With {
.StartDate = reader("StartDate").ToString() & " (" & count & ")",
.CompanyID = reader("company").ToString(),
.Origin = reader("Origin").ToString(),
.OriginName = reader("OriginName").ToString(),
.Status = reader("status").ToString(),
.StatusName = reader("statusname").ToString(),
.Status = reader("status").ToString(),
.FullLegalBusinessName = reader("fullLegalBusinessName"),
.AmountRequestedText = reader("amountRequestedText"),
.HowSoonNeededText = reader("howSoonNeededText"),
.QueueID = reader("QueueID"),
.Company = reader("Company"),
})
End If
companyIDs.Add(reader("company").ToString())
End While
I also noticed that both the .Company and .CompanyID properties in this object are populated from the company column in the reader. Is this intentional, or do you mean to look at a different column for .CompanyID?
Additionally, while I understand your existing search SQL already considers these company rows as distinct, you should probably go back to the drawing board there and rethink the SQL, so that you truly do get distinct records. Perhaps use a nested query or CTE to first find a projection of CompanyID values that match your query, and then join back to your company table to get the details for each company with an ID included in those initial results. If that's not possible, you should consider what it is that makes the rows different, because I promise you that some column IS different, and if you just cull one record or the other you're potentially showing the user bad data from the wrong row.
Use this :
Dim distinctCompanys = companys.GroupBy(Function(x) x.CompanyID).Select(Function(y) y.First())
You can easily filter the collection with LINQ:
Dim companies = companys.Distinct(Function(c) c.CompanyID).ToList
Or use Dictionary(Of String, CompanySearch) instead, for Example:
Dim companies As Dictionary(Of String, CompanySearch)
While reader.Read()
Dim companyID = reader("company").ToString
companies(companyID) = New CompanySearch() With {
.StartDate = reader("StartDate").ToString & " (" & count & ")",
.CompanyID = companyID,
.Origin = reader("Origin").ToString,
.OriginName = reader("OriginName").ToString,
.Status = reader("status").ToString,
.StatusName = reader("statusname").ToString,
.Status = reader("status").ToString,
.FullLegalBusinessName = reader("fullLegalBusinessName"),
.AmountRequestedText = reader("amountRequestedText"),
.HowSoonNeededText = reader("howSoonNeededText"),
.QueueID = reader("QueueID"),
.Company = reader("Company")
}
End While
But I recommend grouping instead, so that you can check for duplicates after:
Dim companiesLookup = companys.ToLookup(Function(c) c.CompanyID)
Dim duplicates = companiesLookup.Where(Function(c) c.Count > 1).ToList

Sorting an Structured object

Sorting:
Dim objReport(0) As stReport
Try
For intK = 1 To 15
objReport(intK).Name = "User" & GetRandomNumber()
objReport(intK).Age = intK
objReport(intK).Misc1 = "data"
Next
Return objReport
Is there any simple way to sort the objReport order by Name?
NOTE: The code is just a sample.
You can sort them using OrderBy Extension Function
objReport = objReport.OrderBy(Function(x) x.Name).ToArray()

How can I add two conditional filters to the same IEnumerable?

How can I fuse these 2 If statements to make both my Droplist filters work together to filter the data? I have 2 droplists (transfilter and Soortfilter) and I want to be able to select something out of droplist 1 and select other thing out of droplist 2 and then press filter and have it show the items that have been selected by filtering with both filters.
# this point I have Return View(query.ToList()) what only shows my filter items from Droplist 1
Function Index(transFilter As TransactieType?, soortfilter As Soort?) As ActionResult
Dim query As IEnumerable(Of Pand)
If Not transFilter.HasValue OrElse transFilter.Value = TransactieType.Beiden Then
query = db.Panden
Else
query = db.Panden.Where(Function(p) p.TransactieType = transFilter.Value)
End If
If Not soortfilter.HasValue OrElse soortfilter.Value = Soort.All Then
query = db.Panden
Else
query = db.Panden.Where(Function(p) p.Soort = soortfilter.Value)
End If
Return View(query.ToList())
End Function
I was trying this but that didn't really work
Function Index(transFilter As TransactieType?, soortfilter As Soort?) As ActionResult
Dim query As IEnumerable(Of Pand)
If Not transFilter.HasValue And soortfilter.HasValue OrElse transFilter.Value = TransactieType.Beiden And soortfilter.Value = Soort.All Then
query = db.Panden
Else
query = db.Panden.Where(Function(p) p.TransactieType = transFilter.Value And p.Soort = soortfilter.Value)
End If
Return View(query.ToList())
The problem is that you're setting query = db.Panden in the first part of both If statements. When you're dealing with incrementally building up a LINQ query, always
Start with a base case. In this case it would be Dim query As IEnumerable(Of Pand)
Add each additional filter directly to that base case using query = query.Where.
Function Index(transFilter As TransactieType?, soortfilter As Soort?) As ActionResult
Dim query As IEnumerable(Of Pand) = db.Panden
If transFilter.HasValue AndAlso transFilter.Value <> TransactieType.Beiden Then
query = query.Where(Function(p) p.TransactieType = transFilter.Value)
End If
If soortfilter.HasValue AndAlso soortfilter.Value <> Soort.All Then
query = query.Where(Function(p) p.Soort = soortfilter.Value)
End If
Return View(query.ToList())
End Function

mongodb query to find field - vb.net

How would I structure a query for mongodB to make a 'stored procedure' or make the request to select an id which is marked active and then delete that field immediately or mark it as inactive; whichever one has the better performance. Here is the collection structure:
db = server.GetDatabase("test")
siteCollection = db("test")
collection = db.GetCollection(Of BsonDocument)("siteids")
Dim book As BsonDocument = New BsonDocument() _
.Add("siteid", BsonValue.Create(BsonType.String)) _
.Add("active", BsonValue.Create(BsonType.String))
collection.Insert(book)
I found the java version and not sure if this will work and what is .net syntax
db.things.find( { x : 4 } , { j : 1 } )
This apparantly finds records where x = 4 but only return where j = 1 so I want one siteid where active = 'N'
Thanks; here is what I have come up with thus far:
' Dim squery = Query.EQ("active", "Y")
Dim squery = Query.EQ("active", "Y")
Dim ssort = SortBy.Null
Dim uupdate = Update.[Set]("active", "N")
Dim result = collection.FindAndModify(squery, ssort, uupdate)
' Dim dresult = collection.FindAs(Of BsonDocument)(squery)
Dim newSiteId As String = dresult.Count
As you can see the first line commented out I thought a simple select would be implemented but that comes back null. Then with the second last statement commented out that too returned value Null.

Join two items from an array using VB

I am creating an array as follows
Dim strFriends(0 to 6) As String
strFriends(0) = "Bianca"
strFriends(1) = "Jeana"
strFriends(2) = "Sam"
strFriends(3) = "Jenna"
strFriends(4) = "Erin"
strFriends(5) = "Carolyn"
strFriends(6) = "Kate"
Dim myFriends As String
myFriends = Join(strFriends, ", ")
MsgBox myFriends
This will produce the following string: "Bianca, Jeana, Sam, Jenna, Erin, Carolyn, Kate"
But I need to retrieve specific items in array and display them as list, something like this:
e.g: If I want to select from strFriends, Kate ,Sam and Bianca
It should list like
Kate
Sam
Bianca
How to perform the task. I am really new to VB so I am confused with this simple task. Can anyone help.
Thank you
Dim strFriends(0 To 6) As String
strFriends(0) = "Bianca"
strFriends(1) = "Jeana"
strFriends(2) = "Sam"
strFriends(3) = "Jenna"
strFriends(4) = "Erin"
strFriends(5) = "Carolyn"
strFriends(6) = "Kate"
Dim objOutput As Text.StringBuilder = New Text.StringBuilder()
For Each strFriend As String In strFriends
Select Case strFriend
Case "Kate", "Sam", "Bianca"
objOutput.AppendLine(strFriend)
End Select
Next
MessageBox.Show(objOutput.ToString())
Or
For Each strFriend As String In strFriends
If MyLogicToDetermineSelected(strFriend) Then
objOutput.AppendLine(strFriend)
End If
Next
It's not clear why you need to pick items from the original array when you already know which items you want, so I won't answer that part of the question. As for displaying each item on it's own line, you can do this with String.Join:
Dim chosenFriends As String() = {"Kate", "Sam", "Bianca"}
Dim output As String = String.Join(Environment.NewLine, chosenFriends)