Evalute part of LINQ expression before translating to SQL statements - vb.net

Dim instanceOfMyClass As New MyClass()
'... Some code to manipulate instanceOfMyClass.MyArrayField
Dim thisYear = DateTime.Today.Year
Dim records = (
From i In dbContext.MyTable
Where i.MyCol >= thisYear - instanceOfMyClass.MyArrayField.Length AndAlso i.MyCol <= thisYear - 1
).ToArray()
Class MyClass
Friend MyArrayField As String()
End Class
Running above code throws an exception because EF6 doesn't know how to translate instanceOfMyClass.MyArrayField.Length to SQL expression. Of course I can do:
Dim anIntermediateVar = instanceOfMyClass.MyArrayField.Length
Dim records = (
From i In dbContext.MyTable
Where i.MyCol >= thisYear - anIntermediateVar AndAlso i.MyCol <= thisYear - 1
).ToArray()
It just feels a bit unintuitive to me. I wonder if there's a syntax/function/whatever to mark a section of expression so that .NET runtime will evaluate the code within before translating? Something like:
From i In dbContext.MyTable
Where i.MyCol >= thisYear - EvalThisFirst(instanceOfMyClass.MyArrayField.Length) AndAlso i.MyCol <= thisYear - 1
so that when EF6 doing LINQ-to-TSQL translation it's translating from:
From i In dbContext.MyTable
Where i.MyCol >= thisYear - 5 AndAlso i.MyCol <= thisYear - 1
Does such mechanism exist?

Related

Problems in the While Loop: Adding a thing to the list only once

I want to make restaurant bookings. As long as the guest is in the hotel, the guest should eat in the morning, at noon and in the evening. I have a booking_of_restaurant class for this. In the form in which the hotel reservation is made, the restaurant is then also booked for the period in question.
My code still books way too much – it would be enough to have one breakfast, one lunch and one dinner 😅. I can't think of how to solve it.
Both start and end dates are given in text boxes with the time. The time is therefore not the default 12 A.M.
Restaurant_reservations As New List(Of booking_of_restaurant)
Private Sub Button_addGuest_Click(sender As Object, e As EventArgs) Handles Button_addGuest.Click
Dim currentDate As Date = Start_date
While currentDate < End_date
If currentDate.Hour >= 7 AndAlso currentDate.Hour < 11 Then
Restaurant_reservations.Add(New booking_of_restaurant(currentDate,
booking_of_restaurant.kind_of_meals.breakfast,
characteristic))
ElseIf currentDate.Hour > 11 AndAlso currentDate.Hour < 14 Then
Restaurant_reservations.Add(New booking_of_restaurant(currentDate,
booking_of_restaurant.kind_of_meals.lunch,
characteristic))
ElseIf currentDate.Hour >= 18 AndAlso currentDate.Hour < 22 Then
Restaurant_reservations.Add(New booking_of_restaurant(currentDate,
booking_of_restaurant.kind_of_meals.dinner,
characteristic))
End If
currentDate = currentDate.AddHours(1)
End While
End Sub
I tried this, but the error is
"booking_of_restaurant.kind_of_meals" is an enumeration type and cannot be used as an expression.
If Not Restaurant_reservations.Last().kind_of_meals = booking_of_restaurant.kind_of_meals.breakfast Then
End If
You are stepping in steps of 1 hour, so the loop is entering for instance the first block ten times (at 1:00, 2:00, 3:00, ...). So probably the easiest would be, stepping to the upper limit of the range, once a booking is made
Private Sub Button_addGuest_Click(sender As Object, e As EventArgs) Handles Button_addGuest.Click
Dim currentDate As Date = Start_date
Dim addHours as Integer = 1
While currentDate < End_date
If currentDate.Hour > 0 AndAlso currentDate.Hour < 11 Then
Restaurant_reservations.Add(New booking_of_restaurant(currentDate,
booking_of_restaurant.kind_of_meals.breakfast,
characteristic))
addHours = 11 - currentDate.Hour
ElseIf currentDate.Hour > 11 AndAlso currentDate.Hour < 14 Then
Restaurant_reservations.Add(New booking_of_restaurant(currentDate,
booking_of_restaurant.kind_of_meals.lunch,
characteristic))
addHours = 14 - currentDate.Hour
ElseIf currentDate.Hour >= 18 AndAlso currentDate.Hour < 22 Then
Restaurant_reservations.Add(New booking_of_restaurant(currentDate,
booking_of_restaurant.kind_of_meals.dinner,
characteristic))
addHours = 22 - currentDate.Hour
End If
currentDate = currentDate.AddHours(addHours)
End While
End Sub

if condition between from time and to time vb.net

i am trying to write a if condition in Vb.net where i would like to call a SQL procedure if the IF condition is satisfied.But the below condition which I am using is not working . Please let me know when i am wrong.
Dim dt As DateTime, hh As Integer, mm As Integer
dt = DateTime.Now
hh = dt.Hour
mm = dt.Minute
If ((hh > 00 or mm > 30) and (hh <= 9 or mm < 30 )) Then
End if
Need help if the if condition is correct .
I guess the condition is that the current time is between 0:30 and 9:30.
Dim now = DateTime.Now
Dim startTime = DateTime.Today.AddMinutes(30)
Dim endTime = DateTime.Today.AddHours(9).AddMinutes(30)
If now > startTime AndAlso now < endTime Then
End If
Note that you should use AndAlso and OrElse instead of And and Or

Translate this Excel formula into VBA code (function)

This is the formula in Excel that I'm trying to convert to VBA code:
=IFERROR(IF(effDate>curDate,0,IF((curDate-effDate+1)>nDays,nDays*(nSpend/365),((nSpend/365)*(curDate-effDate+1))-IF((curDate-effDate+1)-nDays>0,nSpend/365,0))),0)
For checking working purposes here are the values for each variable:
effDate: 1/1/17 (dimmed as value)
curDate: 3/31/17 (dimmed as value)
nDays: 60
nSpend: 1600
Correct answer: 263
I tried to make it work for two days now and I retyped in about a hundred different way and none of them work. The code may work for one cell but it doesn't calculate correctly for the others. Or it doesn't work at all. Here is one of the examples of what I made earlier (name of the function is APFcst):
If effDate > curDate then
APFcst = 0
Exit Function
End if
If (curDate - effDate + 1) > nDays then
APFcst = nDays * (nSpend / 365)
Else
val1 = (nSpend / 365) * (curDate - effDatea + 1)
end if
if (curDate - effDate + 1) - nDays > 0 then
val2 = nSpend / 365
else
val2 = 0
end if
APFcst = val1 - val2
Exit Function
End if
NOTE: everything is dimmed properly, the issue that I'm having is just translating the actual formula so it'll give me the correct answer.
Please help! I've been staring at this for so long that I might not see an obvious solution.
After noticing that the last IF check in your formula is redundant, here's a simplification of your equation:
Function xAPFcst(effDate, curDate, nSpend, nDays) As double
xAPFcst = IIf(effDate > curDate, 0, (nSpend / 365) * Application.Min(nDays, curDate - effDate + 1))
End function
Something like this, maybe possible to shorten it a touch using IIF's and perhaps, looking at using (nSpend / 365) a bit more effectively, i'll take a look again later. I've not properly tested as yet.
Function formula_test(dtCurrentDate As Date, dtEffectiveDate As Date, nDays As Long, nSpend As Double) As Double
On Error GoTo eHandle
If dtEffectiveDate > dtCurrentDate Then
formula_test = 0
Else
If ((dtCurrentDate - dtEffectiveDate) + 1) > nDays Then
formula_test = nDays * (nSpend / 365)
Else
formula_test = ((nSpend / 365) * (dtCurrentDate - dtEffectiveDate + 1))
If (dtCurrentDate - dtCurrentDate + 1) - nDays > 0 Then
formula_test = formula_test - nSpend / 365
End If
End If
End If
Exit Function
eHandle:
formula_test = 0
End Function

Skin detection code always shows "Arithmetic overflow"

Why this simple skin detection code always returns Message=Arithmetic operation resulted in an overflow.
xMax = bmp.Width - 1 : yMax = bmp.Height - 1
For y = 0 To yMax
For x = 0 To xMax
tmpColor = fixColor(bmp.GetPixel(x, y))
If (((tmpColor.R > 95) And (tmpColor.G > 40) And (tmpColor.B > 20) And (tmpColor.R - tmpColor.G > 15) And (tmpColor.R > tmpColor.G) And (tmpColor.R > tmpColor.B)) Or _
((tmpColor.R > 220) And (tmpColor.G > 210) And (tmpColor.B > 170) And (tmpColor.R - tmpColor.G <= 15) And (tmpColor.R > tmpColor.B) And (tmpColor.G > tmpColor.B))) Then bmp.SetPixel(x, y, Color.Black)
Next x
Next y
Assuming that tmpColor is defined as System.Color, an educated guess would be that, when this error occurs tmpColor.G is greater than tmpColor.R, which would render the result less than zero, and unable to be stored into a byte.
One possible solution would be to do this
Dim r as integer = tmpColor.R
Dim g as integer = tmpColor.G
Dim b as integer = tmpColor.B
and then use these new values within your calculation. It would make the code cleaner some (and much cleaner if you were to put casting within that if statement).
Another option would be to re-order the tests relying on that subtraction, and use the AndAlso operator:
(tmpColor.R - tmpColor.G > 15) And (tmpColor.R > tmpColor.G)
'To
(tmpColor.R > tmpColor.G) AndAlso (tmpColor.R - tmpColor.G > 15)
AndAlso is VB.Net's short-circuiting logical-and operator, and will cause evaluation of the expression to stop at the first False. As all you use is Ands, replacing them all with AndAlso might see a minor performance increase.
A combination of these two items might make the code more readable, overall.

VB.net loop through if-then statements?

I have written a private sub which gets the current time and works out which time bracket (from a timespan array) the current time falls into. Given that there are ten time brackets I'm testing for, the code is repetitive and only the integer index of the array and the result integer change between each if statement.
If DateTime.Now.TimeOfDay >= tmeToday(0) AndAlso DateTime.Now.TimeOfDay <= tmeToday(1) Then
intPeriodFrid = 0 'ext morning; 8am - 9am
intNextBell = 1
ElseIf DateTime.Now.TimeOfDay >= tmeToday(1) AndAlso DateTime.Now.TimeOfDay <= tmeToday(2) Then
intPeriodFrid = 1 'morning break; 9am - 9:05am
intNextBell = 2
... ridiculous amounts of repetition later
ElseIf DateTime.Now.TimeOfDay >= tmeToday(10) AndAlso DateTime.Now.TimeOfDay <= tmeToday(11) Then
intPeriodFrid = 10 'ext afternoon; 3:10pm - 4:10pm
intNextBell = 11
End If
Then it hit me I could probably do it like this:
For value As Integer = 0 To 10
If DateTime.Now.TimeOfDay >= tmeToday(value) AndAlso DateTime.Now.TimeOfDay <= tmeToday(value + 1) Then
intPeriodFrid = value
intNextBell = (value + 1)
Exit For
End If
Next
This would/will be my first ever use of a loop (I'm ten weeks into a VB.NET based course), so I lack confidence in this as a solution, will it work? Any weaknesses/problems I need to look out for if I implement this?