Managing Blank field from Linq Query - sql

I am writing a method in VB.Net that runs a LINQ query on my database, and puts the information from the query into textboxes on a form.
Public Sub OpenPartWindow(ByVal partNumber As String)
Using dbContext As New DB_LINQDataContext
Dim query = (From p In dbContext.Parts
Join ppl In dbContext.Part_Price_Logs On p.Part_ID Equals ppl.Part_ID
Where p.Part_Number = partNumber
Select p.Part_Number, p.Part_Description, p.Part_Information, p.Supplier.Supplier_Name, _
p.Part_Manufacturer.Manufacturer_Name, p.Part_Subcategory.Part_Category.Category_Description, _
p.Part_Subcategory.Subcategory_Description, ppl.Cost_Per_Unit, ppl.Discount_Percentage).First()
MessageBox.Show(query.ToString())
txtPartNum.Text = query.Part_Number.ToString()
txtSupplier.Text = query.Supplier_Name.ToString()
txtManufacturer.Text = query.Manufacturer_Name.ToString()
txtPrice.Text = query.Cost_Per_Unit.ToString()
txtDiscount.Text = query.Discount_Percentage.ToString()
txtDescription.Text = query.Part_Description.ToString()
txtInfo.Text = query.Part_Information.ToString()
Me.Show()
End Using
End Sub
The issue I am having right now is with the last field, the txtInfo TextBox. You see the Part_Information field on the database allows NULL values. So when I go to fill the field when the field is null I am getting a NullReferenceException, which is understandable. However I cannot find a way to get around this exception.
I've tried:
If Not IsNothing(query._Part_Information.ToString()) Then
As well as
If query.Part_Information.Length > 0 Then
As If statements to run through first. But I keep getting the error each time. So I am confused on how I am suppose to deal with this error.

You can use either of the following options:
txtInfo.Text = String.Format("{0}", query.Part_Information)
txtInfo.Text = $"{query.Part_Information}" → $ - String Interpolation
txtInfo.Text = query.Part_Information?.ToString() → ?. - Null Conditional Operator
If query.Part_Information is null, the first two expressions result in Sting.Empty and the last one result in Nothing.

Related

Is there an easier way to do this?

I am looping through a listbox, and I need to get the same value you would get if you did .selectvalue, but without selecting the row. This is how I am doing it now, and it seems dumb.
For intCtr = 0 To lstUserRoleAll.Items.Count -1
lstUserRoleAll.SelectedIndex = intCtr
InsertUserRoles(lstUserRoleAll.SelectedValue)
Next
I have read that lstUserRoleAll.Items(intCtr).value should work, but value isn't a member of that. Also, lstUserRoleAll.Items(intCtr).tostring gets me the text "System.Data.DataRowView".
Surely there is a better way to do this.
Here is the code that I use to add the rows:
Dim rsSelectedGroups As DataTable
strSQL = "SELECT UID, Name "
[Rest of query]
rsSelectedGroups = DataAccess.GetDataTable(strSQL)
lstUserRoleCurrent.DataSource = rsSelectedGroups
lstUserRoleCurrent.ValueMember = "UID"
lstUserRoleCurrent.DisplayMember = "Name"
Because I populated the listbox with a datatable, the following code works. I did not realize that is what was being returned.
For intCtr = 0 To lstUserRoleAll.Items.Count
InsertUserRoles(lstUserRoleAll.Items(intCtr).Item("UID"))
Next

Use multiline textbox for user input rather than single line VB.net

Currently my application is working properly using two separate text boxes and the user enters one sku and one order number then clicking a button to run the SQL query. To make this app more efficient I would like to allow the user to enter a list of orders in a multiline textbox but I am not sure how to setup the variable to pass the list to my query.
Current state:
Private Sub btnCancelLines_Click(sender As Object, e As EventArgs) Handles btnCancelLines.Click
MdiParent = Toolbox
Try
Dim orderNum As String = CStr(txtOrder.Text)
Dim skuNum As String = CStr(txtSKU.Text)
SQL.AddParam("#order", txtOrder.Text)
SQL.AddParam("#SKU", txtSKU.Text)
SQL.ExecQuery("update sop10200
set qtycance = qtytoinv, qtytoinv = '0', ATYALLOC = '0', QTYREMAI = '0'
where ITEMNMBR = #sku
and SOPNUMBE = #order;")
If SQL.HasException(True) Then Exit Sub
dgvData.DataSource = SQL.DBDT
LoadGrid()
Catch ex As System.InvalidCastException
MessageBox.Show("Please use numbers",
"Error")
Console.WriteLine("An error occured")
Catch ex As Exception
MessageBox.Show("An unknown error occured",
"Error")
End Try
End Sub
My multiline textbox is txtOrderList obviously I would change my SQL query to an IN statement.
If someone could point me in the right direction I would appreciate it.
There are many ways to accomplish this task.
You could build an XML string from your selections and then pass that into a stored procedure and then create a table variable you could join to.
Create a delimited string you can split inside your call that would insert into a table variable.
For Example:
Dim orderNums As String = String.Join(",", txtOrder.Lines)
SQL.AddParam("#order", orderNums)
'Execute your query...
In your query...
SQL.ExecQuery("DECLARE #tbl TABLE(OrderNums BIGINT);
INSERT INTO #tbl(OrderNums)
SELECT x.value
FROM STRING_SPLIT(#order, ',') x;
UPDATE sop
SET qtycance = qtytoinv, qtytoinv = '0', ATYALLOC = '0', QTYREMAI = '0'
FROM #tbl t
INNER JOIN sop10200 sop
ON sop.SOPNUMBE = t.OrderNums
WHERE sop.ITEMNMBR = #sku;
")
Hopefully this will get you on the right track... The above would update everything in the sop10200 table where the order numbers were provided.
Depending on the database and if you use store procedure or not, there's no easy way. You'll have to built your query with a for loop like this
where ITEMNMBR IN (#sku0, #sku1, ...)
Then add the sku
Dim skus = txtSKU.Text.split(",")
SQL.AddParam("#SKU0", skus(0))
SQL.AddParam("#SKU1", skus(1))
...
This is a quick example, you'll definitely need to use loop to built it properly.
For i As Integer = 0 To skus.length - 1
SQL.AddParam("#SKU" & i, skus(i))
Next
Similar For loop would be needed to build the query.

find files then parse the results before displaying the results

I'm working on an app for our customer service division. The user will enter a print number, and a mfg date. the app will then do a get files returning results of all files found with that drawing number (multiple revisions). the files are named in this format drawingnumber_rev_pages_6-digit date.pdf.
Once I have the list of that drawing number, I then take a right(string) of 10 characters to strip the 6-digit date off, and do a Date.ParseExact to compare to the user input mfg date. I was grabbing anything prior to that date, and showing them in a listbox. the criteria has now changed, and they want me to only show the file that would pertain to that build date. The problem is, I need the first rev prior to that date. and I don't fully understand the (function) portion of my getfiles statement. So I don't know what to search for to even lookup google results. as I search for getfiles, function isn't mentioned, if I look up orderby... function isn't mentioned, is it linq I need to search under? how would you propose I approach this?
original version example
new version, I can filter result and find everything before date ... but what I want is the highest revision before the mfg. date. return a single result.
current version
thank you all- here's my sample code.
Try
Dim results = Directory.GetFiles(fp, f).
OrderByDescending(Function(x) New FileInfo(x).FullName)
For Each result In results
Dim dp As String = ""
Dim d As Date
dp = Strings.Right(result, 10)
dp = Strings.Left(dp, 6)
d = Date.ParseExact(dp, "MMddyy", New Globalization.CultureInfo("en-us"))
Debug.Print(dp)
Debug.Print(d)
Dim udt As String = ""
Dim ud As Date 'user date
udt = Trim(Replace(txtMfgDate.Text, "/", ""))
If udt.ToString.Length = 0 Then lstFound.Items.Add(result)
ud = Date.ParseExact(udt, "MMddyy", New Globalization.CultureInfo("en-us"))
If d.Date <= ud.Date Then
lstFound.Items.Add(result)
End If
Debug.Print(d)
Debug.Print(ud)
If result <> Nothing Then
End If
Next
Catch x As Exception
MessageBox.Show("Error finding file: " & f)
End Try
LINQ can do everything you need with the right conditions. I also tried to clean up some of the code in other ways. I switched the LINQ expression to query comprehension to so I could use Let.
Try
Dim enusCulture = New Globalization.CultureInfo("en-us") ' consider CultureInfo.CurrentCulture instead?
Dim udt As String = Trim(Replace(txtMfgDate.Text, "/", ""))
Dim ud As Date
If udt.Length > 0 Then ud = Date.ParseExact(udt, "MMddyy", enusCulture) ' user mfg date
' 0071911_a_1_072115.pdf
Dim results = From filename In Directory.GetFiles(fp, f)
Let filedate = Date.ParseExact(filename.Substring(filename.Length - 10, 6), "MMddyy", enusCulture)
Where udt.Length = 0 OrElse filedate.Date < ud.Date
Order By filedate Descending
If udt.Length> 0 Then
results = results.Take(1)
End If
lstFound.Items.AddRange(results)
Catch x As Exception
MessageBox.Show("Error finding file: " & f)
End Try
The Function(x) syntax is a lambda expression, and it is part of LINQ method syntax for the OrderByDescending function, if you want to research that.

Strange issue with query design function in access

I have the error message "Data type mismatch in criteria expression" in a query I am making using query builder in access. The problem is caused by a function inside the query.
This is the function :
Function Sudent_Selected_Next_Active_Season(Code_Student, Starting_Date As Date, Code_Project) As Boolean
Dim MyReturn
Dim SQLDate
SQLDate = Format$(Starting_Date, "\#mm\/dd\/yyyy\#")
MyReturn = DCount("[code_student]", "Project_Termination_level_2", "[Code_Student]=" & Code_Student & " and [ending] > " & SQLDate & " and [code_project] <>" & Code_Project)
If IsNull(MyReturn) Then
MyReturn = 0
End If
If MyReturn > 0 Then
Sudent_Selected_Next_Active_Season = True
Else
Sudent_Selected_Next_Active_Season = False
End If
End Function
I tried as criteria 0, -1, "0", "-1", True, False and they all give the same error.
If I remove the criteria and I review the data, all the row are composed of -1 and 0
This is the SQL used.
SELECT Sudent_Selected_Next_Active_Season([t_student].[code_student],[T_Project].[starting_date],[T_project].[code_project]) AS ActiveNextSeason
FROM (T_Project INNER JOIN T_Project_Student ON T_Project.Code_Project = T_Project_Student.Code_Project) INNER JOIN T_Student ON T_Project_Student.Code_Student = T_Student.Code_Student
WHERE (((Sudent_Selected_Next_Active_Season([t_student].[code_student],[T_Project].[starting_date],[T_project].[code_project]))=-1)) OR (((Sudent_Selected_Next_Active_Season([t_student].[code_student],[T_Project].[starting_date],[T_project].[code_project]))=-1));
If anyone could give me an idea of where to search for a solution I would appreciate it. If anyone wants more information please just ask.
not sure why you have the same condition twice in your WHERE clause, but in general, with those errors, you need to convert the data type on one side to match the other.
You could change the return value of your function to integer, cast the boolean return value to integer, or cast the -1 as boolean.
If you've changed the return value of the function to an integer, then the comparison with -1 should not give you a data type conversion error. Try this:
SELECT
s.code_student,p.starting_date,p.code_project,
Sudent_Selected_Next_Active_Season(s.code_student,p.starting_date,p.code_project) AS ActiveNextSeason
FROM
T_Project p INNER JOIN
T_Project_Student ps ON
p.Code_Project = ps.Code_Project INNER JOIN
T_Student s ON
ps.Code_Student = s.Code_Student
WHERE
Sudent_Selected_Next_Active_Season(s.code_student,p.starting_date,p.code_project)=-1

Variant Join in MS Access

I am converting a spreadsheet that had over 80 Sumifs for output.
For a query, I can join 2 tables, but they depend on 6-8 factors that aren't consistent, hence, the sumifs.
I've been successful with right joins in some instances, but most of the time I have to piece meal all of the conditions.
One of my approaches is to write a function like this:
Public Function DetermineCOB_ID(strFund As String, strType As String, strMDEP As String, _
strTier1 As String, strAirGround As Variant, strAcctType As String) As Integer
If strFund = "A82AB" And strType = "Base" And strTier1 = "2 BCT" And strMDEP = "W25D" And strAcctType = "Subordinate_Cmds" Then
DetermineCOB_ID = 1
ElseIf strFund = "A82AC" And strType = "Base" And strMDEP = "W25D" And strAcctType = "Subordinate_Cmds" Then
DetermineCOB_ID = 2
ElseIf strFund = "A82AD" And strType = "Base" And strMDEP = "W25D" And strAirGround = "Ground" And strAcctType = "Subordinate_Cmds" Then
DetermineCOB_ID = 3
Else
DetermineCOB_ID = 0
End If
End Function
But I will have to write 80 separate ElseIf statements.
I'd like to hook up my logic to a control table that the user can change the factors that determine the values.
This would somehow involve a 'variant' join everywhere there is a join where one is not required. I hope I am making sense.
Is there another approach to solving this problem?
Yes, I am working with a back end that leaves a lot to be desired. In the interim, I'm probing for alternate solutions. Do you know a way to make a join respond like a variant variable i.e so it can work with null values. I've tried outer joins but it doesn't really work.