nullable object must have a value vb - vb.net

I have a bigger code block which I have recreated in this simpler example:
Dim evalcheck As Boolean
Dim aEntityId, bEntityId As Integer?
Dim aCheckNumber, bCheckNumber As Integer?
aEntityId = Nothing
bEntityId = Nothing
aCheckNumber = Nothing
bCheckNumber = Nothing
evalcheck = aEntityId = bEntityId And aCheckNumber = bCheckNumber
I get nullable object must have a value when I compare Nothing to Nothing pairs.
Is there a quick fix for the eval part -
evalcheck = aEntityId = bEntityId And aCheckNumber = bCheckNumber

You should really use parentheses for readability. Even then, the comparison is ugly.
If ((aEntityId IsNot Nothing And bEntityId IsNot Nothing) AndAlso (aEntityId = bEntityId)) Or (aEntityId Is Nothing And bEntityId Is Nothing) Then
If ((aCheckNumber IsNot Nothing And bCheckNumber IsNot Nothing) AndAlso (aEntityId = bEntityId)) Or (aCheckNumber Is Nothing And bCheckNumber Is Nothing) Then
evalcheck = True
Else
evalcheck = False
End If
Else
evalcheck = False
End If
I prefer this method better though
Private Function NullableIntsEqual(ByVal a As Integer?, ByVal b As Integer?) As Boolean
If ((a IsNot Nothing And b IsNot Nothing) AndAlso (a = b)) Or (a Is Nothing And b Is Nothing) Then
Return True
Else
Return False
End If
End Function
You evalcheck line becomes
evalcheck = NullableIntsEqual(aEntityId, bEntityId) And NullableIntsEqual(aCheckNumber, bCheckNumber)

Related

vb.net autocad get blockreference winform

i use vb.net To dev winform app. I can take blockreference, block name"Tab1". Now i want Get this block To edit block attribute, but i don't know how to do that,i search on gg but have no result.
Dim appProgID As String = "Autocad.Application"
Dim fname As String = "C:\Users\Kid\Downloads\IDEA FOR TOOL\TEST\TABLE ATTRIBUTE.dwg"
Dim AcadType As Type = Type.GetTypeFromProgID(appProgID)
Dim AcadApp As Object = Activator.CreateInstance(AcadType)
Dim visargs() As Object = New Object(0) {}
visargs(0) = False
AcadApp.GetType().InvokeMember("Visible", BindingFlags.SetProperty, Nothing, AcadApp, visargs, Nothing)
Dim AcadDocs As Object = AcadApp.GetType().InvokeMember(
"Documents", BindingFlags.GetProperty, Nothing, AcadApp, Nothing)
Dim args() As Object = New Object(1) {}
args(0) = fname
args(1) = False
Dim AcDoc As Object = AcadDocs.GetType.InvokeMember(
"Open", BindingFlags.InvokeMethod, Nothing, AcadDocs, args, Nothing)
AcadApp.GetType.InvokeMember(
"ActiveDocument", BindingFlags.GetProperty, Nothing, AcadApp, Nothing, Nothing)
AcDoc = AcadApp.GetType.InvokeMember(
"ActiveDocument", BindingFlags.GetProperty, Nothing, AcadApp, Nothing, Nothing)
Dim AcadModel As Object = AcDoc.GetType.InvokeMember("modelspace", BindingFlags.GetProperty, Nothing, AcDoc, Nothing)
Dim entity As Object
For Each entity In AcadModel
If TypeName(entity) = "IAcadBlockReference" Then
'here i want to take this block has name "tab1"
End If
Next
You don't need to use InvokeMember, VB.NET supports late binding.
Dim acadType As Type = Type.GetTypeFromProgID("AutoCAD.Application")
Dim acadApp = Activator.CreateInstance(acadType)
acadApp.Visible = true
Dim doc = acadApp.Documents.Open("C:\Users\Kid\Downloads\IDEA FOR TOOL\TEST\TABLE ATTRIBUTE.dwg")
Dim entity
For Each entity In doc.ModelSpace
If entity.ObjectName = "AcDbBlockReference" AndAlso _
String.Equals(entity.Name, "Tab1", StringComparison.OrdinalIgnoreCase) Then
Dim att
For Each att In entity.GetAttributes()
If att.TagString = "A" Then
att.TextString = "Your value"
End If
Next
End If
Next
If you want to have autocompletion, you need to download the ObjectARX SDK and add the following COM references to your VS project:
C:\ObjectARX 20..\inc-x64\Autodesk.AutoCAD.Interop.dll
C:\ObjectARX 20..\inc-x64\Autodesk.AutoCAD.Interop.Common.dll
Then you will be able to use typed variables like this:
Dim acadApp As AcadApplication = Activator.CreateInstance(acadType)

Silverlight - Reflection - dynamic class - Inject code in the setter

In Silverlight, I use a Dynamic class. I want to call boolean function before set property, for example :
Private _MyVar as Object
Public Property MyVar as Object
Get
return _MyVar
End Get
Set(value as Object)
If IsUpdateProp(value,"MyVar") Then _myVar = value
End Set
End Property
Private Function IsUpdateProp(value as Object, key as string) as Boolean
If value Is Nothing AndAlso GetValueProperty(key) Is Nothing
OrElse (value IsNot Nothing AndAlso
GetValueProperty(key) IsNot Nothing AndAlso
value.Equals(GetValueProperty(key))) Then
Return False
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(key))
Return True`
End Function
I want to make this with reflection, my code :
Dim dp As DynamicProperty = properties(i)
Dim fb As FieldBuilder = tb.DefineField("_" & dp.Name, dp.Type,
FieldAttributes.Private)
Dim pb As PropertyBuilder = tb.DefineProperty(dp.Name,
PropertyAttributes.HasDefault, dp.Type, Nothing)
Dim isModify = GetType(Dynamic.DynamicClass).GetMethod("SetModifyField",
New Type() {GetType(Object), GetType(String)})
Dim mbSet As MethodBuilder = tb.DefineMethod("set_" & dp.Name,
MethodAttributes.Public Or
MethodAttributes.SpecialName Or
MethodAttributes.HideBySig,
Nothing, New Type() {dp.Type})
Dim genSet As ILGenerator = mbSet.GetILGenerator()
Dim mLabel = genSet.DefineLabel
genSet.Emit(OpCodes.Nop)
genSet.Emit(OpCodes.Ldarg_0)
genSet.Emit(OpCodes.Ldarg_1)
genSet.Emit(OpCodes.Box, dp.Type)
genSet.Emit(OpCodes.Ldstr, dp.Name)
genSet.Emit(OpCodes.Call, isModify)
genSet.Emit(OpCodes.Call, GetType(Convert).GetMethod("ToBoolean",
New Type() {GetType(Object)}))
genSet.Emit(OpCodes.Stloc_0)
genSet.Emit(OpCodes.Ldloc_0)
genSet.Emit(OpCodes.Brfalse_S, mLabel)
genSet.Emit(OpCodes.Ldarg_0)
genSet.Emit(OpCodes.Ldarg_1)
genSet.Emit(OpCodes.Stfld, fb)
genSet.MarkLabel(mLabel)
genSet.Emit(OpCodes.Nop)
genSet.Emit(OpCodes.Nop)
genSet.Emit(OpCodes.Ret)
At runtime, when I call setvalue on my property I get this error message:
System.Security.VerificationException: Cette opération pourrait déstabiliser le runtime." & vbCrLf & " à DynamicClass1.set_MyVar(Nullable`1 )
Thanks

reader with blank or null records

Thought the code would catch empty records but it turns out it has not been and no error.
turns out my function always returns FALSE
Try
conn.Open()
Dim strQuery As String = "Select * FROM [UsersDataTbl] " & _
"WHERE [UserName] = """ & UserName & """"
Dim comm As New Data.OleDb.OleDbCommand(strQuery, conn)
Dim reader As Data.OleDb.OleDbDataReader = comm.ExecuteReader()
While reader.Read()
If noNull(reader("StudentID") = "") _
Or noNull(reader("LastName") = "") _
Or noNull(reader("FirstName") = "") _
Or noNull(reader("Affiliation") = "") Then
BlankFields = True
Else
BlankFields = False
End If
End While
conn.Close()
Catch ex As Exception
ADDED:
found my noNull method:
Public Function noNull(ByRef o As Object) As String
If (o Is Nothing) Then
Return ""
End If
Return o.ToString()
End Function
I process recordfield values like this:
Dim iVal As Integer = NoNull(r.Fields("someintegerfield").Value, "0", False)
Public Function NoNull(ByVal uAny As Object, Optional ByVal uFillString As String = "", Optional ByVal uTreatDecimalNullAsNothing As Boolean = False) As String
Dim sRet As String = String.Empty
If Not Convert.IsDBNull(uAny) AndAlso Not uAny Is Nothing Then
Debug.Assert(uAny.GetType.ToString <> "cField") 'checking if the argument is a "cField" helps me to check whether I passes "r.fields("somefield").value to this function, or if I forgot the ".value")
sRet = uAny
Else
sRet = String.Empty
End If
If StrLen(sRet) = 0 Then
If modStrings.StrLen(uFillString) > 0 Then
sRet = uFillString
End If
End If
If uTreatDecimalNullAsNothing Then
If sRet = "0" Then
sRet = uFillString
End If
End If
Return sRet
End Function
Public Function StrLen(ByVal uString As String) As Integer
If (Not uString Is Nothing) AndAlso (Not uString = "") Then
Return uString.Length
Else
Return 0
End If
End Function
I hope this can help you.
Dim con As New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=H:\yourDB.accdb;")
Dim cb As String = "SELECT * FROM Table1 "
Dim dr As System.Data.OleDb.OleDbDataReader
Dim cmd As New System.Data.OleDb.OleDbCommand
cmd.Connection = con
cmd.CommandText = cb
con.Open()
dr = cmd.ExecuteReader
While dr.Read()
If Not IsDBNull(dr("value1")) Then MessageBox.Show(dr("value1"))
End While
con.Close()
Supposing that the noNull method is something like this
Public Function noNull(dbValue As Object) as Boolean
if dbValue = DBNull.Value OrElse dbValue = "" Then
return True
else
return False
End If
End Function
Then you call it with
....
noNull(reader("LastName") = "")
....
This means that you compare the value of the LastName field to an Empty string and the result is a boolean True or False, but passing a Boolean value to noNull means that it will never be equal to an empty string or to a DBNull.Value and thus it will return always false
You need to call the method with
If noNull(reader("StudentID")) _
Or noNull(reader("LastName")) _
Or noNull(reader("FirstName")) _
Or noNull(reader("Affiliation")) Then
Or without the noNull method
If reader.IsDBNull(reader.GetOrdinal("StudentID")) _
OrElse reader("StudentID") = "" _
OrElse reader.IsDBNull(reader.GetOrdinal("LastName")) _
OrElse reader("LastName") = ""
OrElse reader.IsDBNull(reader.GetOrdinal("FirstName")) _
OrElse reader("FirstName") = "" _
OrElse reader.IsDBNull(reader.GetOrdinal("Affiliation")) _
OrElse reader("Affiliation") = "" Then
BlankFields = True
Else
BlankFields = False
End If
As you can see this is really ugly, so I suppose that a method like noNull iomplemented above could be useful in this context
EDIT Now, looking at the code of your noNull method then it is clear where is the error.
You should just change the parenthesis position.
If noNull(reader("StudentID")) = "" _
Or noNull(reader("LastName")) = "" _
Or noNull(reader("FirstName")) = "" _
Or noNull(reader("Affiliation")) = "" Then

Importing logon hours from active directory to SQL Server

I am trying to pull all the users from the Active Directory, I am able to pull all the records but when I read the data in the tables it displays as SYSTEM.BYTE[](for logonhours), need to convert before inserting that into SQL table.
I did a googling and found some solution like first converting that into byte then into a string and inserting it, where you can read the data, but I am not able to implement that.
Can anyone help me out?
I am inserting into SQL Server 2005 and importing all the data using SSIS ( since there is a limitation on ADSI when you query, you get only 1000 records I am using a custom script and setting a page default to more than 1000 to retrive all the records from active directory)
below is my custom script how I am pulling my records from ADSI:
' Microsoft SQL Server Integration Services user script component
' This is your new script component in Microsoft Visual Basic .NET
' ScriptMain is the entrypoint class for script components
Option Strict Off
Imports System
Imports System.Data
Imports System.DirectoryServices
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Public Class ScriptMain
Inherits UserComponent
Public Overrides Sub CreateNewOutputRows()
Dim arrayDomains As String()
ReDim arrayDomains(1)
arrayDomains(0) = "LDAP://DC=cba,DC=acb,DC=com"
arrayDomains(1) = "LDAP://DC=abc,DC=bca,DC=com"
Dim Domain As String
For Each Domain In arrayDomains
Dim objSearch As New DirectorySearcher()
objSearch.SearchRoot = New DirectoryEntry(Domain)
objSearch.Filter = "(&(objectclass=user)(objectcategory=Person)(samAccountType=805306368))"
'(|(&(!(groupType:1.2.840.113556.1.4.803:=1))(groupType:1.2.840.113556.1.4.804:=14))(samAccountType=805306368))
objSearch.SearchScope = SearchScope.Subtree
objSearch.PageSize = 999
objSearch.ServerTimeLimit = New TimeSpan(0, 15, 0)
objSearch.ClientTimeout = New TimeSpan(0, 30, 0)
objSearch.PropertiesToLoad.Add("cn")
objSearch.PropertiesToLoad.Add("c")
objSearch.PropertiesToLoad.Add("department")
objSearch.PropertiesToLoad.Add("displayName")
objSearch.PropertiesToLoad.Add("distinguishedName")
objSearch.PropertiesToLoad.Add("employeeID")
objSearch.PropertiesToLoad.Add("extensionAttribute14")
objSearch.PropertiesToLoad.Add("extensionAttribute2")
objSearch.PropertiesToLoad.Add("givenName")
objSearch.PropertiesToLoad.Add("l")
objSearch.PropertiesToLoad.Add("lastLogon")
objSearch.PropertiesToLoad.Add("logonHours")
objSearch.PropertiesToLoad.Add("mail")
objSearch.PropertiesToLoad.Add("manager")
objSearch.PropertiesToLoad.Add("physicalDeliveryOfficeName")
objSearch.PropertiesToLoad.Add("postalCode")
objSearch.PropertiesToLoad.Add("pwdLastSet")
objSearch.PropertiesToLoad.Add("sn")
objSearch.PropertiesToLoad.Add("st")
objSearch.PropertiesToLoad.Add("streetAddress")
objSearch.PropertiesToLoad.Add("telephoneNumber")
objSearch.PropertiesToLoad.Add("title")
objSearch.PropertiesToLoad.Add("userAccountControl")
objSearch.PropertiesToLoad.Add("whenCreated")
Dim colQueryResults As SearchResultCollection
colQueryResults = objSearch.FindAll()
Dim objResult As SearchResult
For Each objResult In colQueryResults
'Console.WriteLine("3")
'
' Add rows by calling AddRow method on member variable called "<Output Name>Buffer"
' E.g., MyOutputBuffer.AddRow() if your output was named "My Output"
'
Output0Buffer.AddRow()
If objResult.Properties.Contains("cn") AndAlso objResult.Properties("cn")(0) IsNot Nothing Then
Output0Buffer.cn = objResult.Properties("cn")(0).ToString()
End If
If objResult.Properties.Contains("c") AndAlso objResult.Properties("c")(0) IsNot Nothing Then
Output0Buffer.c = objResult.Properties("c")(0).ToString()
End If
If objResult.Properties.Contains("department") AndAlso objResult.Properties("department")(0) IsNot Nothing Then
Output0Buffer.Department = objResult.Properties("department")(0).ToString()
End If
If objResult.Properties.Contains("displayName") AndAlso objResult.Properties("displayname")(0) IsNot Nothing Then
Output0Buffer.DisplayName = objResult.Properties("displayName")(0).ToString()
End If
If objResult.Properties.Contains("distinguishedName") AndAlso objResult.Properties("distinguishedName")(0) IsNot Nothing Then
Output0Buffer.DistinguishedName = objResult.Properties("distinguishedName")(0).ToString()
End If
If objResult.Properties.Contains("employeeID") AndAlso objResult.Properties("employeeID")(0) IsNot Nothing Then
Output0Buffer.EmployeeID = objResult.Properties("employeeID")(0).ToString()
End If
If objResult.Properties.Contains("extensionAttribute14") AndAlso objResult.Properties("extensionAttribute14")(0) IsNot Nothing Then
Output0Buffer.ExtensionAttribute14 = objResult.Properties("extensionAttribute14")(0).ToString()
End If
If objResult.Properties.Contains("extensionAttribute2") AndAlso objResult.Properties("extensionAttribute2")(0) IsNot Nothing Then
Output0Buffer.ExtensionAttribute2 = objResult.Properties("extensionAttribute2")(0).ToString()
End If
If objResult.Properties.Contains("givenName") AndAlso objResult.Properties("givenName")(0) IsNot Nothing Then
Output0Buffer.GivenName = objResult.Properties("givenName")(0).ToString()
End If
If objResult.Properties.Contains("l") AndAlso objResult.Properties("l")(0) IsNot Nothing Then
Output0Buffer.L = objResult.Properties("l")(0).ToString()
End If
If objResult.Properties.Contains("lastLogon") AndAlso objResult.Properties("lastLogon")(0) <> 0 AndAlso objResult.Properties("lastLogon")(0) IsNot Nothing Then
Output0Buffer.LastLogon = DateTime.Parse(DateTime.FromFileTime(objResult.Properties("lastLogon")(0).ToString()))
End If
'If objResult.Properties.Contains("pwdLastSet") AndAlso objResult.Properties("pwdLastSet")(0) <> 0 AndAlso objResult.Properties("pwdLastSet")(0) IsNot Nothing Then
' Output0Buffer.PwdLastSet = DateTime.Parse(DateTime.FromFileTime(objResult.Properties("pwdLastSet")(0)).ToString())
'End If
If objResult.Properties.Contains("logonHours") AndAlso objResult.Properties("logonHours")(0) IsNot Nothing Then
Output0Buffer.LogonHours = objResult.Properties("logonHours")(0).ToString()
End If
If objResult.Properties.Contains("mail") AndAlso objResult.Properties("mail")(0) IsNot Nothing Then
Output0Buffer.Mail = objResult.Properties("mail")(0).ToString()
End If
If objResult.Properties.Contains("manager") AndAlso objResult.Properties("manager")(0) IsNot Nothing Then
Output0Buffer.Manager = objResult.Properties("manager")(0).ToString()
End If
If objResult.Properties.Contains("physicalDeliveryOfficeName") AndAlso objResult.Properties("physicalDeliveryOfficeName")(0) IsNot Nothing Then
Output0Buffer.PhysicalDeliveryOfficeName = objResult.Properties("physicalDeliveryOfficeName")(0).ToString()
End If
If objResult.Properties.Contains("postalCode") AndAlso objResult.Properties("postalCode")(0) IsNot Nothing Then
Output0Buffer.PostalCode = objResult.Properties("postalCode")(0).ToString()
End If
If objResult.Properties.Contains("pwdLastSet") AndAlso objResult.Properties("pwdLastSet")(0) <> 0 AndAlso objResult.Properties("pwdLastSet")(0) IsNot Nothing Then
Output0Buffer.PwdLastSet = DateTime.Parse(DateTime.FromFileTime(objResult.Properties("pwdLastSet")(0)).ToString())
End If
'If objResult.Properties.Contains("pwdLastSet") AndAlso objResult.Properties("pwdLastSet")(0) IsNot Nothing Then
' Output0Buffer.PwdLastSet = objResult.Properties("pwdLastSet")(0).ToString()
'End If
If objResult.Properties.Contains("sn") AndAlso objResult.Properties("sn")(0) IsNot Nothing Then
Output0Buffer.Sn = objResult.Properties("sn")(0).ToString()
End If
If objResult.Properties.Contains("st") AndAlso objResult.Properties("st")(0) IsNot Nothing Then
Output0Buffer.St = objResult.Properties("st")(0).ToString()
End If
If objResult.Properties.Contains("streetAddress") AndAlso objResult.Properties("streetAddress")(0) IsNot Nothing Then
Output0Buffer.StreetAddress = objResult.Properties("streetAddress")(0).ToString()
End If
If objResult.Properties.Contains("telephoneNumber") AndAlso objResult.Properties("telephoneNumber")(0) IsNot Nothing Then
Output0Buffer.TelephoneNumber = objResult.Properties("telephoneNumber")(0).ToString()
End If
If objResult.Properties.Contains("title") AndAlso objResult.Properties("title")(0) IsNot Nothing Then
Output0Buffer.Title = objResult.Properties("title")(0).ToString()
End If
If objResult.Properties.Contains("userAccountControl") AndAlso objResult.Properties("userAccountControl")(0) IsNot Nothing Then
Output0Buffer.UserAccountControl = objResult.Properties("userAccountControl")(0).ToString()
End If
If objResult.Properties.Contains("whenCreated") AndAlso objResult.Properties("whenCreated")(0) IsNot Nothing Then
Output0Buffer.WhenCreated = CDate(objResult.Properties("whenCreated")(0).ToString())
End If
Next
Next
End Sub
End Class
You need to create a function to convert that OctetString to a String. If you directly convert it that will show System.Byte[] this is because OctetString is a Byte Array type. Fof the function do something like this
Private Function ConvertByteArrayToString(xArray As Byte()) As String
Dim [sByte] As String = ""
For Each x As Byte In xArray
[sByte] += x.ToString() & " "
Next
Return [sByte]
End Function
and use it like such
If objResult.Properties.Contains("logonHours") AndAlso objResult.Properties("logonHours")(0) IsNot Nothing Then
Output0Buffer.LogonHours = ConvertByteArrayToString(objResult.Properties("logonHours"))
End If

How do I invoke HasValue on a nullable property of an object via reflection?

This function loops all properties of an object to create the updatequery to save te object to the DB.
We had to make some changes to it because of the introduction of nullable properties.
If the property is nullable we would like to check the 'HasValue' property.
This does works when it has a value. When the property has no value we get an 'Non-static method requires a target'-error at the CBool-line
Any suggestions?
An other way to check the 'HasValue'-prop of a property using reflection?
Thanks.
Private Function GetUpdateQuery(ByVal obj As Object, ByRef params As List(Of SqlParameter), Optional ByVal excl As String() = Nothing) As String
Dim sql As String = String.Empty
Dim props As PropertyInfo() = obj.GetType().GetProperties
If excl Is Nothing Then
excl = New String() {}
End If
For Each prop As PropertyInfo In props
Try
If Not excl.Contains(prop.Name) And prop.CanWrite = True Then
sql &= String.Format("{0} = #{1},", prop.Name, prop.Name)
Dim param As SqlParameter
Dim value As Object
If prop.PropertyType.IsGenericType AndAlso prop.PropertyType.GetGenericTypeDefinition() = GetType(Nullable(Of )) Then
If CBool(prop.PropertyType.GetProperty("HasValue").GetValue(prop.GetValue(obj, Nothing), Nothing)) Then
value = prop.GetValue(obj, Nothing)
Else
value = DBNull.Value
End If
Else
If prop.GetValue(obj, Nothing) = Nothing Then
value = DBNull.Value
Else
value = prop.GetValue(obj, Nothing)
End If
End If
param = ConnSql.CreateParameter("#" & prop.Name, value)
params.Add(param)
End If
Catch ex As Exception
End Try
Next
sql = sql.Substring(0, sql.Length - 1)
Return sql
End Function
You do not need the following If. You can remove it.
If prop.PropertyType.IsGenericType AndAlso prop.PropertyType.GetGenericTypeDefinition() = GetType(Nullable(Of )) Then
BUT you do need to fix the following If:
If prop.GetValue(obj, Nothing) = Nothing Then
to
If prop.GetValue(obj, Nothing) IS Nothing Then
--
Complete code:
Private Function GetUpdateQuery(ByVal obj As Object, ByRef params As List(Of SqlParameter), Optional ByVal excl As String() = Nothing) As String
Dim sql As String = String.Empty
Dim props As PropertyInfo() = obj.GetType().GetProperties
If excl Is Nothing Then
excl = New String() {}
End If
For Each prop As PropertyInfo In props
If Not excl.Contains(prop.Name) And prop.CanWrite = True Then
sql &= String.Format("{0} = #{1},", prop.Name, prop.Name)
Dim param As SqlParameter
Dim value As Object
If prop.GetValue(obj, Nothing) Is Nothing Then
value = DBNull.Value
Else
value = prop.GetValue(obj, Nothing)
End If
param = ConnSql.CreateParameter("#" & prop.Name, value)
params.Add(param)
End If
Next
sql = sql.Substring(0, sql.Length - 1)
Return sql
End Function