I have two Layes Classes Business Layer And Data Layer And i have The Main class i called DatabaseManager contain all functions i need for stored procedures
I search on these errors I cannot find solutions
First Error in DatabaseManager class is :
implicit conversion from object to integer
Public Function ExecuteScalar(ByVal sql As String) As Object
Dim cmd As New SqlCommand(sql) With {
.CommandType = CommandType.Text,
.Connection = Connection
}
Dim retval As Integer = ExecuteScalar(cmd)
Return retval
End Function
In Data Layer Class i have this code :
Friend Function Get_Last_Visits_Type(ByRef cmd As SqlCommand)
Dim retval As Integer
cmd = New SqlCommand("Get_Last_Visits_Type")
retval = dm.ExecuteScalar(cmd)
Return retval
End Function
I got two errors here
function without an 'as' clause return type of object assumed
And
implicit conversion from object to integer
When Form Loaded i put this code on Load action :
TxtVisitTypeID.Text = Val(p.Get_Last_Visits_Type)
And i got this error :
implicit conversion from Double to String
Thanks...
Quite a few problems here as mentioned in comments:
Avoid naming a function anything that is a reserved word in the scope of your project at the very least: ExecuteScalar is a method of SqlCommand so use something like MyExecuteScalar instead.
Dim retval As Integer = ExecuteScalar(cmd) probably should be Dim retval As Integer = cmd.ExecuteScalar() unless you want a recursion (which I doubt). (Refer 1.)
Turn Option Strict on in your project settings. As mentioned, ALWAYS have this on. (And I prefer to have Option Explicit on and Option Infer off as well for similar reasons.)
With compile options set as in 3. you will have (valid) compilation errors pertaining to type conversion (at least), with a good chance of resulting in working code once you fix them. Eg Dim retval As Integer = Ctype(cmd.ExecuteScalar(), Integer) (if you're sure that the result of the query will be Integer, otherwise you will need to test and/or error trap).
Connection isn't defined anywhere: .Connection = Connection. You don't pass it nor declare it.
Since retval is declared as an Integer then the return type can also be tightened up to Integer as well, rather than Object.
Your second function has no return type.
What is dm? Not declared/defined.
Consider using Using blocks to close-and-dispose of SQL connection and command on exit.
CommandType.Text is the default so you only need to state it by way of explanation.
Here's what I'd do with your first function:
Public Function MyExecuteScalar(ByVal sql As String) As Integer
Try
Using con As New SqlConnection(sql)
Using cmd As New SqlCommand(sql, con)
Return CType(cmd.ExecuteScalar(), Integer)
End Using
End Using
Catch
Return -1 ' Or something recognizable as invalid, or simply Throw
End Try
End Function
Addressing the first function:
This code is too abstract to be useful. The name of the function is bad. It appears to be recursive but the value you pass back to the function is not a string but a command. If the line of code is Dim retval As Integer = cmd.ExecuteScalar(), then .ExecuteScalar() returns an Object. You cannot convert an Object to an Integer without a conversion method. If you are declaring retval as an Integer why would you have typed your function As Object? I won't even get into the connection problem here. I suggest you delete the function and start again.
Addressing the second function:
Why are you passing the command ByRef? This function has no connection at all! How do you expect it to execute anything? Same problem with retval As Integer and ExecuteScalar returning an Object.
Again, delete and start again.
Now to the code in Form.Load:
Val went out with VB6. I can give unanticipated results. Guess what, Val returns a Double. A .Text property expects a string. Also you appear to be calling the function you showed us above. That function asks for the calling code to provide an argument, namely an SqlCommand object.
My suggestions:
Forget about layers and try to learn the basics of data access with ADO.net. Turn on Option Strict now and forever. Ask new questions with a single problem. Tell us what line the error occurs on. You have been advised before that functions require a datatype but it doesn't seem to sink in.
Related
I encountered an issue with Function and Procedure while experimenting with some code, as below:
Module mod1
Class ExampleApp
Dim textvalue as String = "dGhpcyBpcyBhbiBleGFtcGxlIG9mIGEgdGV4dC4="
Dim string1 as String = "Convert.FromBase64String(input)"
Public Function DecodeB64(ByVal input As String) As String
Return System.Text.Encoding.UTF8.GetString(string1)
End Function
End Class
End Module
The question is, is it possible to encode the statement inside the Public Function before it gets executed?
I have seen some cases where they implemented it on PHP Scripts, where the whole script is encoded before it gets executed. I have tried my best in applying the same concept by storing "Convert.FromBase64String(input)" to a string variable but I'm encountering an issue like this:
Value of type 'String' cannot be converted to '1-Dimensional array of
Byte'
When I don't apply this concept, the text in base64 gets decoded smoothly. My main goal is that I want to obscure the statement or group of statements as much as possible. What seems to be the problem in this Error?
You have 2 mistakes below in the example code:
First, you should know that Convert.FromBase64String() returns
Byte() array, hence you can't assign it to string variable/field.
Second, Encoding.GetString() requires Byte() array as parameter,
but you're passing string to it, hence InvalidCastException occurred.
The correct usage of them should be like this:
Public Function DecodeB64(ByVal input As String) As String
' make sure the input string is Base64 formatted
Dim bytearray As Byte() = Convert.FromBase64String(input)
' decoding from byte array
Return System.Text.Encoding.UTF8.GetString(bytearray)
End Function
' usage
Dim textvalue as String = "dGhpcyBpcyBhbiBleGFtcGxlIG9mIGEgdGV4dC4="
Dim result As String = DecodeB64(textvalue)
Working example: .NET Fiddle demo
I've recently implemented reflection to replace the more tedious aspects of our data retrieval from a SQL database. The old code would look something like this:
_dr = _cmd.ExecuteReader (_dr is the SQLDataReader)
While _dr.Read (_row is a class object with public properties)
_row.Property1 = Convert.ToInt16(_dr("Prop1"))
_row.Property2 = Convert.ToInt16(_dr("Prop2"))
_row.Property3 = Convert.ToInt16(_dr("Prop3"))
If IsDBNull(_dr("Prop4")) = False Then _row.Prop4 = _dr("Prop4")
...
Since my code base has a lot of functionality like this, reflection seemed like a good bet to simplify it and make future coding easier. How to assign datareader data into generic List ( of T ) has a great answer that was practically like magic for my needs and easily translated into VB. For easy reference:
Public Shared Function GenericGet(Of T As {Class, New})(ByVal reader As SqlDataReader, ByVal typeString As String)
'Dim results As New List(Of T)()
Dim results As Object
If typeString = "List" Then
results = New List(Of T)()
End If
Dim type As Type = GetType(T)
Try
If reader.Read() Then
' at least one row: resolve the properties
Dim props As PropertyInfo() = New PropertyInfo(reader.FieldCount - 1) {}
For i As Integer = 0 To props.Length - 1
Dim prop = type.GetProperty(reader.GetName(i), BindingFlags.Instance Or BindingFlags.[Public])
If prop IsNot Nothing AndAlso prop.CanWrite Then
props(i) = prop
End If
Next
Do
Dim obj = New T()
For i As Integer = 0 To props.Length - 1
Dim prop = props(i)
If prop Is Nothing Then
Continue For
End If
' not mapped
Dim val As Object = If(reader.IsDBNull(i), Nothing, reader(i))
If val IsNot Nothing Then SetValue(obj, prop, val)
Next
If typeString = "List" Then
results.Add(obj)
Else
results = obj
End If
Loop While reader.Read()
End If
Catch ex As Exception
Helpers.LogMessage("Error: " + ex.Message + ". Stacktrace: " + ex.StackTrace)
End Try
Return results
End Function
The only caveat with this is that it is somewhat slower.
My question is how to optimize. Sample code I find online is all in C# and does not convert neatly into VB. Scenario 4 here seems like exactly what I want, but converting it to VB gives all kinds of errors (Using CodeFusion or converter.Telerik.com).
Has anyone done this in VB before? Or can anyone translate what's in that last link?
Any help's appreciated.
Couple ideas for you.
Don't use the DataReader when reading ALL records at once, it is slower than using a DataAdapter.
When you use the DataAdapter to fill a DataSet, you can iterate through the rows and columns which does NOT use reflection and will be much faster.
I have a program I created (and many other programmers do this too) that generate the code from a database for me. Each table and row is a class that is specifically named an generated in such a way that I can use intellisense and prevents many run-time errors by making them compile-time errors when data changes. This is very much like the EntityFramework but lighter because it fits MY specific needs.
I have the follow code in my program where I hit a SQLCe database to append the results into a list. That part works, but instead of exiting the function 'QueryDB' it goes to the else statement and runs the function again, which will return a null value. I designed it this way becuase I wanted to check to make sure the database is open before I try to execute the SQL statement, and if it's not open, call the method to open it and run through the function again.
Public Function QueryDB(ByVal strSQL As String) As List(Of String)
Dim reader As SqlCeDataReader
Dim results As New List(Of String)
Using cmdAdd As New SqlCeCommand(strSQL, conn)
If Me.checkConnection Then
reader = cmdAdd.ExecuteReader()
Do While reader.Read
results.Add(reader.GetString(0))
Loop
Return results
Exit Function
Else
connectPlansdb()
QueryDB(strSQL) 'does not exit function when done and goes through the function again
End If
End Using
End Function
The second problem I have is when I try to populate the list into a combo box in my form class where I call out to the database and use the returned list to populate my combo box. I can't seem to figure out how to get the code to deal with the list.
Private Sub cmbInvestmentStrategy_DropDown(sender As System.Object, e As System.EventArgs) Handles cmbInvestmentStrategy.DropDown
Dim strat As New clsInvestmentStrategies()
Dim invStrat As New List(Of String)
invStrat = strat.getInvestmentStrategies() 'String cannot be converted to List(pf String)
cmbInvestmentStrategy.Items.Add(invStrat) 'Error 3 Value of type 'System.Collections.Generic.List(Of String)' _
'cannot be converted to '1-dimensional array of Object'.
End Sub
Any help would be greatly appreciated.
Thanks!
Your QueryDB method has a big flaw. If the database is unavailable (connectivity problems, database offline or wrong connection string), there will be an infinite loop. Your query DB method should just query the database. You could wrap it in another method responsible for connecting to the database, but you don't want to retry database connection infinitely.
As for your second method:
invStrat = strat.getInvestmentStrategies() 'String cannot be converted to List(Of String)
Error is pretty clear here. getInvestementStrategies returns a single String and cannot be converted to a list. It should return a List(Of String), or at least some collection of strings, I suppose?
cmbInvestmentStrategy.Items.Add(invStrat) 'Error 3 Value of type 'System.Collections.Generic.List(Of String)' _
'cannot be converted to '1-dimensional array of Object'.
Items.Add will add a single element to the combobox. You should loop through the invStrat values, and call Add for every item. Alternatively, you could use the AddRange method, but this method expects an Array, not a List.
I'm getting the following warning message...
Return type of function 'ConnectionNew' is not CLS-compliant.
...for this function:
Public Function ConnectionNew(ByVal DataBaseName As String) As MySqlConnection
Dim connection As MySqlConnection = Nothing
connection = getConnection(DataBaseName())
Return connection
End Function
What does this message mean, and how can I fix it?
It is because you are returning an object of a type that's not CLS compliant. Nothing you can do about that, you didn't write the type. Just acknowledge that you know that it isn't compliant, it isn't otherwise likely to cause any problems. Unless you use the function in another language that doesn't support all the .NET types. Fix:
<CLSCompliant(False)> _
Public Function ConnectionNew(ByVal DataBaseName As String) As MySqlConnection
'' etc...
End Function
Ok, just needing a 2nd set of eyes looking at this to make sure the error isn't something else other than my LINQ code here. Here's the function class itself:
Public Function GetJacketByPolicyID(ByVal jacketID As Int32) As tblPolicy
Dim db As New DEVDataContext()
Dim j As tblPolicy = db.tblPolicies.Single(Function(p) p.policyNumber = jacketID)
Return j
End Function
and here is the code which calls this class function in the web control form itself:
Dim p As tblPolicy
Dim j As New Jackets()
p = j.GetJacketByPolicyID(3000050)
For some reason it's flagging the 2nd line in the GetJacketByPolicyID function saying the specified cast is not valid. So I'm guessing it's something I'm doing wrong. I'm sure the tblPolicy/tblPolicies class works right since I can create a new instance of a tblPolicy and set a few variables by hand and return it, so that's not it. I've also checked the datarow I'm fetching and there's no null values in the record, so that shouldn't be it either.Any help much appreciated.
This would seem to get what you are looking for. Not sure why you are passing in a function for a simple query like this.
Public Function GetJacketByPolicyID(ByVal jacketID As Int32) As tblPolicy
Dim _jacket as tblPolicy
Using _db As New DEVDataContext()
_jacket = (From _j In db.tblPolicies Where _j.policyNumber.Equals(jacketID) Select _j).Single()
End Using
Return _jacket
End Function