I have a search page that has a series of 3 dropdowns that the user can use to limit the search results. Each of the dropdowns has an initial value of ALL. If any have a value other than ALL I need to include that as a WHERE statement.
This is where I become stuck. My Linq Select is...
Dim myComponents = From searchComponents In dc.Components _
Where searchComponents.Type = ddl_Type.SelectedValue _
AndAlso searchComponents.Size = ddl_Size.SelectedValue _
AndAlso searchComponents.WR = ddl_WR.SelectedValue _
Select searchCompnents)
At the moment my search will include all ddl selectedValues. I need to remove any that have a value of ALL. I hope I've explained correctly. Example if ddl_Size.SelectedValue = "ALL" then my statement would be...
Dim myComponents = From searchComponents In dc.Components _
Where searchComponents.Type = ddl_Type.SelectedValue _
AndAlso searchComponents.WR = ddl_WR.SelectedValue _
Select searchCompnents)
How can I achieve this in code. Thanks
Dim myComponents = From searchComponents In dc.Components _
Where (ddl_Type.SelectedValue = "ALL" OrElse searchComponents.Type = ddl_Type.SelectedValue) _
AndAlso (ddl_Size.SelectedValue = "ALL" OrElse searchComponents.Size = ddl_Size.SelectedValue) _
AndAlso (ddl_WR.SelectedValue = "ALL" OrElse searchComponents.WR = ddl_WR.SelectedValue) _
Select searchCompnents)
Related
I am trying to build aKendo bar chart. I need the number of tickets opened, and tickets closed. I need that result grouped by month. Here is my LINQ
Dim openTickets = (From t In queue _
Where _
(t.CreateDate.Year = Convert.ToDateTime(DateTime.Now).Year)
Group t By _
ID = CType(t.CreateDate.Month, Integer), _
Month = CType(t.CreateDate.ToString("MMMM"), String) _
Into g = Group _
Select New With _
{.Month = Month.Substring(0, 3), .Opened = g.Where(Function(t) t.CreateDate.Month = ID).Count(Function(t) t.Id)})
Dim closedTickets = (From t In queue _
Where _
(t.CloseDate.Year = Convert.ToDateTime(DateTime.Now).Year)
Group t By _
ID = CType(t.CloseDate.Month, Integer), _
Month = CType(t.CloseDate.ToString("MMMM"), String) _
Into g = Group _
Select New With _
{.Month = Month.Substring(0, 3), .Closed = g.Where(Function(t) t.CloseDate.Month = ID).Count(Function(t) t.Id)})
Dim ticketCount = openTickets.Union(closedTickets)
When I try this, I get "WhereSelectEnumerableIterator". If I change the second query so that the name is ".Opened" and not ".Closed" it works, but then I do not know my count for "closed".
Ultimately I am trying to get an output of an array to supply the chart... similar to this:
[{"Month":"Apr","Opened":138,"Closed":150}
INSTEAD OF
[{"Month":"Apr","Opened":138,"Closed":0},{"Month":"Apr","Opened":0,"Closed":150}
You need to use a Join statement to merge the two and keep the values distinct. Something like this:
Dim tickets = From open In openTickets _
Join closed In closedTickets _
On open.Month Equals closed.Month _
Select New With _
{.Month = open.Month, .Opened = open.Opened, .Closed = closed.Closed}
I'd normally do this in C# but since I've got to get this code in this particular assembly which is a vb.net one, I'm stuck.
Here's my linq query:
Dim i As Integer = 0
Dim oldAndCurrentIntersectionOnNames = From currentApplicant In currentApplicants _
Group Join oldApplicant In oldApplicants _
On _
New With {Key .FirstName = currentApplicant.FirstName, _
Key .LastName = currentApplicant.LastName} _
Equals _
New With {Key .FirstName = oldApplicant.FirstName, _
Key .LastName = oldApplicant.LastName} Into applicants = Group _
From applicant In applicants.DefaultIfEmpty(New ApplicantNameDetails()) _
Select New ApplicantNameDetails() With _
{ _
.Index = i+=1, _
.FirstName = CStr(IIf(Not currentApplicant.FirstName Is Nothing, currentApplicant.FirstName, Nothing)), _
.OldFirstName = CStr(IIf(Not applicant.FirstName Is Nothing, applicant.FirstName, Nothing)), _
.LastName = CStr(IIf(Not currentApplicant.LastName Is Nothing, currentApplicant.LastName, Nothing)), _
.OldLastName = CStr(IIf(Not applicant.LastName Is Nothing, applicant.LastName, Nothing)) _
}
You'll see the .Index = i+=1
This was my attempt to do what I'd quite happily do in C# (i.e. Index = i++) in VB. Unfortunately the VB compiler doesn't like that.
Has anybody got any suggestions as to how I'd do this in VB.
Thanks in advance
Essentially, you can’t. If you want the Linq query to get consecutive values, use a special (so-called “generator”) class that has an IncrementAndGet (or simply Next) method for your integer.
class IntegerGenerator
private state as integer = 0
public function Next() as integer
dim oldState = state
state += 1
return oldState
end function
end class
There is an overload of the Select method that lets you use the index of the item on the result collection. http://msdn.microsoft.com/en-us/library/bb534869.aspx
You could split your query in two parts to use it (untested)
Dim q = From currentApplicant In currentApplicants _
Group Join oldApplicant In oldApplicants On _
New With {Key.FirstName = currentApplicant.FirstName, _
Key.LastName = currentApplicant.LastName} _
Equals _
New With {Key.FirstName = oldApplicant.FirstName, _
Key.LastName = oldApplicant.LastName} Into applicants = Group _
From applicant In applicants.DefaultIfEmpty(New ApplicantNameDetails())
Dim oldAndCurrentIntersectionOnNames = _
q.Select(Function(x, i) New ApplicantNameDetails() With _
{ _
.Index = i, _
.FirstName = CStr(IIf(Not x.currentApplicant.FirstName Is Nothing, x.currentApplicant.FirstName, Nothing)), _
.OldFirstName = CStr(IIf(Not x.applicant.FirstName Is Nothing, x.applicant.FirstName, Nothing)), _
.LastName = CStr(IIf(Not x.currentApplicant.LastName Is Nothing, x.currentApplicant.LastName, Nothing)), _
.OldLastName = CStr(IIf(Not x.applicant.LastName Is Nothing, x.applicant.LastName, Nothing)) _
})
I have a LINQ Query:
bikersList = (From c In ngBikersDataContext.Reg_Bikers _
Order By c.L_Name _
Select New Bikers() With { _
.BikerID = c.BikerID, _
.F_Name = c.F_Name, _
.M_Name = c.M_Name, _
.L_Name = c.L_Name, _
.MyID = c.MyID, _
.Site = c.Site.GetValueOrDefault, _
.bk_Building = c.bk_Building, _
.bk_City = c.bk_City, _
.bk_Zip = c.bk_Zip.GetValueOrDefault, _
.bk_Phone = c.bk_phone, _
.email = c.email, _
.DeptZone = c.DeptZone, _
.QuartID = c.QuartID.GetValueOrDefault, _
.BikerDays = c.BikerDays.GetValueOrDefault, _
.BikerMiles = c.BikerMiles.GetValueOrDefault, _
.BikerTime = c.BikerTime.GetValueOrDefault, _
.BKLockID = c.BKLockID.GetValueOrDefault, _
.bk_Start_DT = c.bk_Start_DT, _
.bk_End_DT = c.bk_End_DT, _
.bk_Quarter = c.bk_Quarter.GetValueOrDefault, _
.bk_Year = c.bk_Year.GetValueOrDefault, _
.bk_Comments = c.bk_Comments, _
.IsActive = c.IsActive.GetValueOrDefault _
}).ToList()
This works great and sorts on L_Name. But I am trying to allow the user to sort the gridview themselves. So I am passing in the SortExpression as a string. But I don't know how to incorperate the SortExpression into the LINQ Query.
I tried
Order By c. & SortExpression
But that did not work.
You should check out something called a Dynamic Query in Linq.
Using the LINQ Dynamic Query Library
Here's an article that talks about dynamic sorting with linq using a sortexpression string:
http://www.codeproject.com/KB/recipes/Generic_Sorting.aspx
Basically, you'll need to build the expression tree manually.
(this code is from the link above)
Public Function Sort(ByVal source As IEnumerable(Of T), _
ByVal sortBy As String, _
ByVal sortDirection As String) As IEnumerable(Of T)
Dim param = Expression.Parameter(GetType(T), "item")
Dim sortExpression = Expression.Lambda(Of Func(Of T, Object))_
(Expression.Convert(Expression.[Property](param, sortBy), _
GetType(Object)), param)
Select Case sortDirection.ToLower
Case "asc"
Return source.AsQueryable().OrderBy(sortExpression)
Case Else
Return source.AsQueryable().OrderByDescending(sortExpression)
End Select
End Function
I have a listbox on my xaml form that I bound to a List(Of MyType) property. I populated this list like so:
Dim fields As List(Of CheckableFields) = New List(Of CheckableFields)
Using context As ITIPEntities = New ITIPEntities()
Try
Dim propertyInfoList As List(Of PropertyInfo) = GetType(PC).GetProperties().ToList()
For Each pI In propertyInfoList
If (pI.PropertyType <> GetType(EntityState) _
And pI.PropertyType <> GetType(EntityKey) _
And pI.PropertyType <> GetType(EntityCollection(Of DiskDrive)) _
And pI.PropertyType <> GetType(EntityCollection(Of Memory)) _
And pI.PropertyType <> GetType(EntityCollection(Of Monitor)) _
And pI.PropertyType <> GetType(EntityCollection(Of Network)) _
And pI.PropertyType <> GetType(EntityCollection(Of Processor))) Then
fields.Add(New CheckableFields(pI.Name))
End If
Next
Catch ex As Exception
End Try
End Using
Now I'm at the point where the user selects the fields they want included in a report and I need to iterate over the required fields. This is my linq query:
For Each checkedField In _requiredFields
If checkedField.IsChecked Then
If checkedField.FieldData IsNot Nothing AndAlso checkedField.FieldData.Trim IsNot String.Empty Then
Dim fieldData As String = checkedField.FieldData
Dim name As String = checkedField.Name
lquery = From comp In lquery Where CType(comp.GetType.GetProperty(name).GetValue(comp, Nothing), String).ToUpper.Contains(fieldData.ToUpper) Select comp
End If
End If
Next
Which throws the exception that linq doesn't recognize the GetValue method.
How can I get the property values dynamically?
Edit:
I couldn't find a way to do this with Linq to Entities, but I did find a way without Linq that works for me:
For Each field In _requiredFields
If field.IsChecked Then
reportGenerator.AllFields.Add(field.Name)
If field.FieldData IsNot Nothing Then
For i As Integer = pcs.Count - 1 To 0 Step -1
Dim compPropertyValue As String = CType(pcs(i).GetType().GetProperty(field.Name).GetValue(pcs(i), Nothing), String).ToUpper()
If Not compPropertyValue.Contains(field.FieldData.ToUpper()) Then
pcs.RemoveAt(i)
End If
Next i
End If
End If
Next
This construct is not supported in LINQ-to-Entities. It is a designed limitation.
Try using Entity SQL instead as shown in the following example:
"SELECT VALUE comp From COMPs AS comp WHERE comp." & name & ".ToUpper().Contains(" & fieldData & ".ToUpper()"
Why does the following query raise the error below for a row with a NULL value for barrel when I explicitly filter out those rows in the Where clause?
Dim query = From row As dbDataSet.conformalRow In dbDataSet.Tables("conformal") _
Where Not IsDBNull(row.Cal) AndAlso tiCal_drop.Text = row.Cal _
AndAlso Not IsDBNull(row.Tran) AndAlso tiTrans_drop.Text = row.Tran _
AndAlso Not IsDBNull(row.barrel) _
Select row.barrel
If query.Count() > 0 Then tiBarrel_txt.Text = query(0)
Run-time exception thrown : System.Data.StrongTypingException - The value for column 'barrel' in table 'conformal' is DBNull.
How should my query / condition be rewritten to work as I intended?
By default, in strongly typed datasets, properties throw that exception if the field is null. You need to use the generated Is[Field]Null method :
Dim query = From row As dbDataSet.conformalRow In dbDataSet.Tables("conformal") _
Where Not row.IsCalNull() AndAlso tiCal_drop.Text = row.Cal _
AndAlso Not row.IsTranNull() AndAlso tiTrans_drop.Text = row.Tran _
AndAlso Not row.IsbarrelNull() _
Select row.barrel
If query.Count() > 0 Then tiBarrel_txt.Text = query(0)
Or the DataRow.IsNull method :
Dim query = From row As dbDataSet.conformalRow In dbDataSet.Tables("conformal") _
Where Not row.IsNull("Cal") AndAlso tiCal_drop.Text = row.Cal _
AndAlso Not row.IsNull("Tran") AndAlso tiTrans_drop.Text = row.Tran _
AndAlso Not row.IsNull("barrel") _
Select row.barrel
If query.Count() > 0 Then tiBarrel_txt.Text = query(0)
This worked for me.
Dim query = From row As dbDataSet.conformalRow
In dbDataSet.Tables("conformal") _
Where row.Cal.Length > 0 AndAlso tiCal_drop.Text = row.Cal _
AndAlso row.Tran.Length > 0 AndAlso tiTrans_drop.Text = row.Tran _
AndAlso row.barrel.Length > 0 _
Select row.barrel