Linq shortening - vb.net

Is it possible to shorten this function into a single line / couple of lines?
Public Function countrySelector() As List(Of String)
Dim myString As New List(Of String)
Dim countryTitle As List(Of Entities.AttributeValue) = _PageVals.Where(Function(x) x.TabDescription = "Country").ToList()
myString = countryTitle.Where(Function(x) x.AttributeId = Entities.AttributeTypes.TITLE).Select(Function(y) y.Value).ToList()
Return myString
End Function

Try This,
myString = _PageVals.Where(Function(x) x.TabDescription = "Country" AndAlso x.AttributeId = Entities.AttributeTypes.TITLE).Select(Function(y) y.Value).ToList()

Try the following
Return _PageVals _
.Where(Function(x) x.TabDescription = "Country") _
.Where(Function(x) x.AttributeId = Entities.AttributeTypes.TITLE) _
.Select(Function(y) y.Value) _
.ToList()

Or you can use this way
myString = (From C in _PageVals Where C.TabDescription = "Country" AndAlso C.AttributeId = Entities.AttributeTypes.TITLE Select C.Value).ToList()

Related

How build dynamic where clause with string argument

I try to buid a method to add a where clause to a Linq-to-SQL request (return an IQueryable). I try several methods but always use ToString, Indexof... but this result is a sql request take all element and the filter made in linq. I see request in SQL Server profiler.
I want a method to do it with result is a sql request with where include inside
I work in Visual Studio 2017 with SQL Server 2016. I code in vb.net
I see an interesting thing in linq dynamic library. But I can't to adapt to my situation
<Extension()> _
Public Function Where(ByVal source As IQueryable, ByVal predicate As String, ByVal ParamArray values() As Object) As IQueryable
If source Is Nothing Then Throw New ArgumentNullException("source")
If predicate Is Nothing Then Throw New ArgumentNullException("predicate")
Dim lambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, GetType(Boolean), predicate, values)
Return source.Provider.CreateQuery( _
Expression.Call( _
GetType(Queryable), "Where", _
New Type() {source.ElementType}, _
source.Expression, Expression.Quote(lambda)))
End Function
But I don't need all this complex strucutre. It's some years I buid my utilities. But Need to upgrade it. Here my code of my utilities
<Extension()>
Public Function Where(ByVal source As IQueryable, ByVal predicate As String) As IQueryable
Dim param = Expression.Parameter(GetType(String), "x")
Return source.Provider.CreateQuery(
Expression.Call(
GetType(Queryable), "Where",
New Type() {source.ElementType},
source.Expression, Expression.Quote(Expression.Lambda(Expression.Constant(predicate), param))))
End Function
Public Function TFOAppliqueFiltreTri(Of T, MaClassDatas As Class)(Origins As IQueryable(Of T), ByVal MesDonnees As TableFullOption.PagerTabEnCours(Of MaClassDatas)) As IQueryable(of T)
Dim retour As New TableFullOption.LstRetour
'Colonne de filtre
Dim strWh As String = ""
Dim Filtredrecords As IQueryable(Of T)
For Each Sort In MesDonnees.MesOptions
Dim colName = Sort.ColName
If strWh.Length > 0 Then strWh = strWh & " AND "
strWh = strWh & String.Format(colName & " like '%{0}%'", Sort.Search)
Next
If strWh.Length > 0 Then
Filtredrecords = Origins.Where(strWh) '<- Here call Where
Else
Filtredrecords = Origins
End If
Return Filtredrecords
End Function
I get this error:
Aucune méthode générique 'Where' sur le type 'System.Linq.Queryable' n'est compatible avec les arguments de type et les arguments fournis..
Then my problem is to write correctly lambda expression. My predicate argument is : Column1 like '%aaa%'. I want rewrite where method of dynamicLinq to accept string argument :Column1 like '%aaa%' directly
Thanks for your help
Finally after lot of reading in google and few feelings and certainly lot of chance.
Public Function Where(Of TEntity)(source As IQueryable(Of TEntity), searchColumn As List(Of String), searchValue As String) As IQueryable(Of TEntity)
Dim cond As Expression = Nothing
Dim ParamExpr = Expression.Parameter(GetType(TEntity), "x")
Dim conCat2 = GetType(String).GetMethod("Concat", New Type() {GetType(String), GetType(String)})
Dim conCat4 = GetType(String).GetMethod("Concat", New Type() {GetType(String), GetType(String), GetType(String), GetType(String)})
Dim Delim = Expression.Constant("/")
Dim DateName = GetType(SqlFunctions).GetMethod("DateName", New Type() {GetType(String), GetType(Nullable(Of DateTime))})
Dim DatePart = GetType(SqlFunctions).GetMethod("DatePart", New Type() {GetType(String), GetType(Nullable(Of DateTime))})
Dim DblToString = GetType(SqlFunctions).GetMethod("StringConvert", New Type() {GetType(Nullable(Of Double))})
For Each cn In searchColumn
For Each colName In cn.Split("|")
If Not colName.estVide Then
Dim body As Expression = ParamExpr
For Each member In colName.Split(".")
body = Expression.PropertyOrField(body, member)
Next
Dim Tostr As Expression
If body.Type.FullName.Contains("String") Then
Tostr = body
ElseIf body.Type.FullName.Contains("DateTime") Then
Dim day = Expression.Call(Expression.Call(conCat2, Expression.Constant("0"), Expression.Call(DateName, Expression.Constant("day"), body)), "Substring", Nothing, Expression.Constant(0), Expression.Constant(2))
Dim Month = Expression.Call(DatePart, Expression.Constant("MM"), body)
Dim toDouble = Expression.Convert(Month, GetType(Nullable(Of Double)))
Dim mois = Expression.Call(conCat2, Expression.Constant("0"), Expression.Call(Expression.Call(DblToString, toDouble), "Trim", Nothing))
Dim an = Expression.Call(DateName, Expression.Constant("year"), body)
Tostr = Expression.Call(conCat2, Expression.Call(conCat4, day, Delim, mois, Delim), an)
Else
Tostr = Expression.Call(body, "Convert.ToString", Nothing)
'Tostr = Expression.Convert(body, GetType(String))
End If
Dim condPart = Expression.Call(Expression.Call(Tostr, "ToLower", Nothing), "Contains", Nothing, Expression.Call(Expression.Constant(searchValue), "ToLower", Nothing))
If cond Is Nothing Then
cond = condPart
Else
cond = Expression.OrElse(cond, condPart)
End If
End If
Next
Next
Return source.Provider.CreateQuery(Of TEntity)(Expression.Call(GetType(Queryable), "Where", New Type() {GetType(TEntity)}, source.Expression, Expression.Lambda(cond, ParamExpr)))
End Function
Now I've dynamic filter which generated a SQL request with complete clause where

How to add items in anonymous type and retrieve list of item

I have a DataTable in the variable dtLatencyValues.
I select data from this DataTable into a list of an anonymous type:
Dim _Latency = dtLatencyValues.AsEnumerable()
.Where(Function(x) x("Customer_Name") = str1(0).CustName AndAlso x("Site_Name") = str1(j).sitname)
.Select(Function(x) New With
{
.CommLat = x("Committed_Value"),
.ActLat = x("ActualLatencyVal"),
.ToContry = x("Site_To_Name")
})
.OrderBy(Function(a) a.ToContry)
.DefaultIfEmpty().ToList()
I want to add :
Dim temp = New With {.CommLat = "-", .ActLat = "-", .ToContry = str1(j).sitname}
into my _Latency list and then retrieve data from the final _Latency list.
You can simply use Add or Insert:
Dim _Latency = dtLatencyValues.AsEnumerable()...ToList()
Dim temp = New With {.CommLat = "-", .ActLat = "-", .ToContry = str1(j).sitname}
_Latency.Insert(0, temp) ' insert as first element '
' or '
_Latency.Add(temp) ' insert as last element '
You will probably want to set Option Strict On to help avoid some issues like this. Your problem is that the properties of the anonymous type created by the LINQ query are all typed as Object, since DataRow.Item (the x("field name") in your code) returns Object. When you want to add an item, the anonymous types need to match, and AnonymousType(Of Object, Object, Object) doesn't match AnonymousType(Of String, String, String).
If you change your query to use the correct types, you should be able to add new items more easily, e.g. (not sure if these are the correct types for your data!):
Dim _Latency = dtLatencyValues.AsEnumerable() _
.Where(Function(x) x.Field(Of String)("Customer_Name") = str1(0).CustName AndAlso x.Field(Of String)("Site_Name") = str1(j).sitname) _
.Select(Function(x) New With
{
.CommLat = x.Field(Of String)("Committed_Value"),
.ActLat = x.Field(Of String)("ActualLatencyVal"),
.ToContry = x.Field(Of String)("Site_To_Name")
}) _
.OrderBy(Function(a) a.ToContry) _
.DefaultIfEmpty().ToList()
_Latency.Add(New With {.CommLat = "-", .ActLat = "-", .ToContry = str1(j).sitname})
You may need to add a reference to System.Data.DataSetExtensions.dll for the .Field(Of String) calls to work.
EDIT
Here's a complete working example - VS2013 console project.
Option Strict On
Option Explicit On
Option Infer On
Module Module1
Sub Main()
Dim dtLatencyValues = New DataTable()
dtLatencyValues.Columns.Add("Customer_Name", GetType(String))
dtLatencyValues.Columns.Add("Site_Name", GetType(String))
dtLatencyValues.Columns.Add("Committed_Value", GetType(String))
dtLatencyValues.Columns.Add("ActualLatencyVal", GetType(String))
dtLatencyValues.Columns.Add("Site_To_Name", GetType(String))
dtLatencyValues.Rows.Add("CustA", "SiteA", "Com1", "Act1", "STN1")
dtLatencyValues.Rows.Add("CustA", "SiteA", "Com2", "Act2", "STN2")
dtLatencyValues.Rows.Add("CustA", "SiteB", "Com1", "Act1", "STN1")
dtLatencyValues.Rows.Add("CustB", "SiteB", "Com1", "Act1", "STN1")
Dim custName = "CustA"
Dim siteName = "SiteA"
Dim _Latency = dtLatencyValues.AsEnumerable() _
.Where(Function(x) x.Field(Of String)("Customer_Name") = custName AndAlso x.Field(Of String)("Site_Name") = siteName) _
.Select(Function(x) New With
{
.CommLat = x.Field(Of String)("Committed_Value"),
.ActLat = x.Field(Of String)("ActualLatencyVal"),
.ToContry = x.Field(Of String)("Site_To_Name")
}) _
.OrderBy(Function(a) a.ToContry) _
.DefaultIfEmpty().ToList()
_Latency.Add(New With {.CommLat = "-", .ActLat = "-", .ToContry = siteName})
End Sub
End Module
Setting a breakpoint at the End Sub line and inspecting _Latency shows:

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

Can you add an If Statement in a LINQ(XML) query?

I feel this function is too long. I can separate it into two functions, but I would prefer to keep them in one for this.
Public Function getTempList(ByVal applicationType As String) As List(Of String)
Dim doc As XDocument = New XDocument
If My.Settings.sortKey = "alpha" Then
Dim XMLquery = From c In doc.<applications>.<app> _
Where c.<appFav>.Value = "true" And c.<appType>.Value = applicationType
Order By CStr(c.<appName>.Value)
Select c.<appName>
Dim tempList As New List(Of String)
For Each result In XMLquery
tempList.Add(result.Value)
Next
Return tempList
ElseIf My.Settings.sortKey = "fav" Then ' ------------------------------------------------------------------------------------
Dim XMLquery = From c In doc.<applications>.<app> _
Where c.<appFav>.Value = "true" And c.<appType>.Value = applicationType
Order By CInt(c.<appClick>.Value) Descending
Select c.<appName>
Dim tempList As New List(Of String)
For Each result In XMLquery
tempList.Add(result.Value)
Next
Return tempList
End If
End Function
Can I somehow put the if statement in the LINQ query itself. The only thing that needs to change here is the order the list is in. Or, is there another way to order the results I am returning ?
I think this would be the simplest:
Public Function getTempList(ByVal applicationType As String) As List(Of String)
Dim doc As XDocument = New XDocument
Dim XMLquery = _
From c In doc.<applications>.<app> _
Where c.<appFav>.Value = "true" And c.<appType>.Value = applicationType _
Select c
If My.Settings.sortKey = "alpha" Then
XMLquery = XMLquery.OrderBy(Function(c) CStr(c.<appName>.Value))
ElseIf My.Settings.sortKey = "fav" Then
XMLquery = XMLquery.OrderByDescending(Function(c) CInt(c.<appClick>.Value))
End If
Return XMLquery.Select(Function(x) x.<appName>.Value).ToList()
End Function
Try this,
Public Function getTempList(ByVal applicationType As String) As List(Of String)
Dim doc As XDocument = New XDocument
Dim XMLquery = From c In doc.<applications>.<app> _
Where c.<appFav>.Value = "true" And c.<appType>.Value = applicationType
Select c
Dim tempList As New List(Of String)
If My.Settings.sortKey = "alpha" Then
XMLquery = XMLquery.OrderBy(Function(c) CStr(c.<appName>.Value))
ElseIf My.Settings.sortKey = "fav" Then
XMLquery = XMLquery.OrderByDescending(Function(c) CInt(c.<appClick>.Value))
End If
For Each result In XMLquery
tempList.Add(result.<appName>.Value)
Next
Return tempList
End Function
You dont need to repeat the whole query.
You can do something like:
Pardon me for VB syntax, I usually code in C#.
Public Function getTempList(ByVal applicationType As String) As List(Of String)
Dim doc As XDocument = New XDocument
Dim tempList As New List(Of String)
Dim XMLquery = From c In doc.<applications>.<app> _
Where c.<appFav>.Value = "true" And c.<appType>.Value = applicationType
Select c.<appName>
If My.Settings.sortKey = "aplha" Then
Order XMLQuery By CStr(c.<appName>.Value) // convert to VB code
If My.Settings.sortKey = "fav" Then
Order XMLQuery By CInt(c.<appClick>.Value) Descending //convert to VB code
For Each result In XMLquery
tempList.Add(result.Value)
Next
Return tempList
End Function

WHERE IN clause using VB.NET in Entity Framework

I have two CheckboxLists. Based on the items checked, the checked values are concatenated into a comma separated string and passed to my entity framework method. The result would be a List(Of Entity).
I want to convert
SELECT *
FROM dbo.Findings /*Below criteria is added only if any of the values are checked*/
WHERE FindingCategoryId IN (<Checked Values>)
AND FindingSeverityId IN (<CheckBoxValues>)
I am unable to find an equivalent for IN for VB.Net in EF.
I looked at the C# post here and came up with the below code. I get an error as
Unable to create a constant value of type 'System.Object'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
How can I use the IN clause in Vb.Net? Any help is appreciated.
My code:
Public Function Findings(ByVal findingSeverity As String, ByVal findingCategory As String) As List(Of Finding)
Dim aTypeLoanId As Integer = If(Not IsNothing(AuditTypeLoanId), AuditTypeLoanId, -1)
Dim findingTargetId = CInt(FindingTarget.LoanHeader)
Using e As New LQCEntities()
Dim result = (From f In e.FindingEntities _
From hmd In e.HeaderMetaDataEntities.Where(Function(h) h.MetaDataId = f.TargetId).DefaultIfEmpty() _
From cl In e.CheckListEntities.Where(Function(c) c.CheckListId = f.TargetId).DefaultIfEmpty() _
Where f.AuditTypeLoanId = aTypeLoanId _
Select New Finding With _
{
.FindingId = f.FindingId, _
.FindingCategoryId = f.FindingCategoryId, _
.FindingSeverityId = f.FindingSeverityId, _
.EnteredBy = f.ADUser.DisplayName, _
.EnteredDate = f.EnteredDate _
})
Dim fsArray() = Nothing
Dim fcArray() = Nothing
If (Not String.IsNullOrEmpty(findingSeverity)) Then
Dim fs = findingSeverity.Split(",")
For i As Integer = 0 To fs.Count - 1
Dim j As Integer = 0
If (Integer.TryParse(fs(i), j)) Then
ReDim Preserve fsArray(i)
fsArray(i) = j
End If
Next
If (fsArray.Count > 0) Then
result = result.Where(Function(i) fsArray.Contains(i.FindingSeverityId))
End If
End If
If (Not String.IsNullOrEmpty(findingCategory)) Then
Dim fc = findingCategory.Split(",")
For i As Integer = 0 To fc.Count - 1
Dim j As Integer = 0
If (Integer.TryParse(fc(i), j)) Then
ReDim Preserve fcArray(i)
fcArray(i) = j
End If
Next
If (fcArray.Count > 0) Then
result = result.Where(Function(i) fcArray.Contains(i.FindingCategoryId))
End If
End If
Return result.ToList()
End Using
End Function
I changed the fsArray and fcArray to a List(Of Integer) and it worked.
Code is as below:
Public Function Findings(ByVal findingSeverity As String, ByVal findingCategory As String) As List(Of Finding)
Dim aTypeLoanId As Integer = If(Not IsNothing(AuditTypeLoanId), AuditTypeLoanId, -1)
Dim findingTargetId = CInt(FindingTarget.LoanHeader)
Using e As New LQCEntities()
Dim result = (From f In e.FindingEntities _
From hmd In e.HeaderMetaDataEntities.Where(Function(h) h.MetaDataId = f.TargetId).DefaultIfEmpty() _
From cl In e.CheckListEntities.Where(Function(c) c.CheckListId = f.TargetId).DefaultIfEmpty() _
Where f.AuditTypeLoanId = aTypeLoanId _
Select New Finding With _
{
.FindingId = f.FindingId, _
.AuditTypeLoanId = f.AuditTypeLoanId, _
.FindingCategoryId = f.FindingCategoryId, _
.CategoryDescription = f.FindingCategory.CategoryDescription, _
.FindingSeverityId = f.FindingSeverityId, _
.SeverityDescription = f.FindingSeverity.SeverityDescription, _
.TargetId = f.TargetId, _
.UserResponse = f.UserResponse, _
.Field = If(f.FindingTargetId = findingTargetId, hmd.ColumnDescription, cl.CheckListDesc), _
.OldValue = f.OldValue, _
.NewValue = f.NewValue, _
.Comments = f.Comments, _
.EnteredBy = f.ADUser.DisplayName, _
.EnteredDate = f.EnteredDate _
})
If (Not String.IsNullOrEmpty(findingSeverity)) Then
Dim fsList As New List(Of Integer)
Dim fs = findingSeverity.Split(",")
For i As Integer = 0 To fs.Count - 1
Dim j As Integer = 0
If (Integer.TryParse(fs(i), j)) Then
fsList.Add(j)
End If
Next
If (fsList.Count > 0) Then
result = result.Where(Function(i) fsList.Contains(i.FindingSeverityId))
End If
End If
If (Not String.IsNullOrEmpty(findingCategory)) Then
Dim fc = findingCategory.Split(",")
Dim fcList As New List(Of Integer)
For i As Integer = 0 To fc.Count - 1
Dim j As Integer = 0
If (Integer.TryParse(fc(i), j)) Then
fcList.Add(j)
End If
Next
If (fcList.Count > 0) Then
result = result.Where(Function(i) fcList.Contains(i.FindingCategoryId))
End If
End If
Return result.ToList()
End Using
End Function