I am new to the Entity Framework, and am struggling with what I hope is a basic problem. My code is here:
Dim accounts As List(Of STUDENT) =
(From a In SA.STUDENTs
Where (a.MATRIC_NO.Contains(matric) And a.FIRST_NAME.Contains(firstName) And a.MIDDLE_NAMES.Contains(middleName) And a.SURNAME.Contains(lastName) And a.PREFERRED_NAME.Contains(preferredName))
Select a).ToList
The query runs fine, until one of the search fields is NULL in the database. If, for instance, a matric number is entered in the seach interface but middle name is left blank, the query will not return any records if middle name is NULL in the database. If middle name is a blank space in the database then it will return the record.
Can anyone offer any pointers?
Many thanks!
You can add an extra check in your query. For example:
public function filterList(IEnumerable list, string name)
{
var filtered_list = list.Where(x=> x.Name.Contains(name) || string.IsNullorWhitespace(name)).ToList();
return filtered_list;
}
So you can see, if the name variable is empty, all elements will return true, so all elements will be return (no real filter applied).
So basically, you can change all filters from
something.Contains(anotherthing)
to
something.Contains(anotherthing) || string.IsnullOrWhitespace(anotherthing)
(From a In SA.STUDENTs
Where isnull(a.MATRIC_NO.Contains(matric) And a.FIRST_NAME.Contains(firstName) And a.MIDDLE_NAMES.Contains(middleName) And a.SURNAME.Contains(lastName) And a.PREFERRED_NAME.Contains(preferredName))
Select a).ToList
Like this `:select * from tbl where statusid = isnull(#statusid,statusid)
try like this ..
Dim get_rmf_2 = From rmf In t_rmf _
Where Not IsDBNull(rmf!NIVP) AndAlso rmf!NIVP = nivp_rap
this is in VB I think this is works fine
I managed to solve this using a different approach. If there was no value entered for a particular field, leave it out the query. I accomplished this using predicates, as below:
'create the base query
Dim accounts =
(From a In SA.STUDENTs
Select a)
'create predicates for each condition required in the query
If matric <> "" Then
accounts = accounts.Where(Function(m) m.MATRIC_NO.Contains(matric))
End If
If firstName <> "" Then
accounts = accounts.Where(Function(f) f.FIRST_NAME.Contains(firstName))
End If
If middleName <> "" Then
accounts = accounts.Where(Function(mn) mn.MIDDLE_NAMES.Contains(middleName))
End If
If lastName <> "" Then
accounts = accounts.Where(Function(l) l.SURNAME.Contains(lastName))
End If
If preferredName <> "" Then
accounts = accounts.Where(Function(p) p.PREFERRED_NAME.Contains(preferredName))
End If
'execute the query
Dim accountlist = accounts.ToList
'return the results
Return accountlist
If anyone can see anything wrong with this, or any gotchas that I'm unaware of, please let me know! I'm very new to LINQ to Entities, and LINQ in general!
Related
I have a question about using LINQ to access a Database and trying to make use of it's version of accessing the LIKE comparison operator.
I know that LINQ has .Contains(), .StartsWith(), and .EndsWith() as comparison methods. However I am wondering if there is a way to programatically imcorporate SQL Wildcards into a LINQ statement without explicitly using these query operators. Let me explain my situation.
I am writing a program that accesses a database, and part of the program is a search window which the user can use to help them find specific database data. I would like to try and incorporate SQL Wildcards into the textbox fields for these search pages.
For example if a user enters the input 17% I'd want the program to check for anything in that specific column that starts with a 17. The same is true with %17 and 17 where I'd want it to search for columns that end with, and contain the values.
Currently, this is the code I have for my search method:
Public Function Data_Search(sData As List(Of String), DB As CustomDataContext) As DataGridView
Dim gridData As New DataGridView
Dim query = From p In DB.Parts
Select p.Part_Number, p.Part_Description, p.Supplier.Supplier_Name
for i = 0 To sData.Count - 1
If Not sData(i).ToString() = "" Then
Select Case i
Case 0
Dim partNum As String = sData(i).ToString()
query = query.Where(Function(x) x.Part_Number.Contains(partNum))
Case 1
Dim description As String = sData(i).ToString()
query = query.Where(Function(x) x.Part_Description.Contains(description))
Case 2
Dim supp As String = sData(i).ToString()
query = query.Where(Function(x) x.Supplier_Name.Contains(supp))
End Select
End If
Next
gridData.DataSource = query.ToList()
Return gridData
End Function
So right now I am trying to see if there is a way for me to modify the code in a way that doesn't essentially involve me putting a substring search into each Case section to determine if I should be using StartsWith(), Contains(), or EndsWith.
Thanks for your time.
If you are using LINQ to SQL, and you are talking to Microsoft SQL Server, then you can use SQLMethods.Like to implement SQL LIKE:
query = query.Where(Function(x) SQLMethods.Like(x.Part_Number, partNum))
When filter criteria is passed to my LINQ query, no problem:
Dim statesSelected As String = {‘GA’,’FL’}
Dim results As IEnumerable(Of Person) = _
From p As Person in dc.Persons _
Where statesSelected.Contains(p.StateCode)
HOWEVER, if no filter criteria are selected, then I want ALL states returned (instead of none which is what the above would do). How can I do this, please? I realize I could have an IF statement around the query, but in reality I’ll have many filters (and will want to handle them all within the one query).
Thanks for any help.
I am not sure if this would translate to SQL, but you can try this approach:
Dim results As IEnumerable(Of Person) = _
From p As Person in dc.Persons _
Where statesSelected Is Nothing OrElse statesSelected.Contains(p.StateCode)
In this case if your variable statesSelected is nothing then only the first part of query would be executed, otherwise first part would be true and only second condition would matter
Try this out:
Dim results As IEnumerable(Of Person) = _
From p As Person In Persons
Where If(statesSelected.Length < 1, p.StateCode <> "", statesSelected.Contains(p.StateCode))
What it's doing is checking to make sure statesSelected has elements. If not, it simply brings back all elements. If there values in statesSelected, it brings back the ones that contain that state.
The magic is happening in the ternary If() : https://msdn.microsoft.com/en-us/library/bb513985.aspx?f=255&MSPPError=-2147217396
I am trying to convert sql to entity and I need to select distinct items. I thought this would work but its returning all the rows instead of the distinct items.
Dim OrderNos = (From r In Orders.R3Delivery Where r.mainOrderNumber <> "" Select r).Distinct().ToList()
For Each thisentry In OrderNos
cbOrderNumbers.DisplayMember = thisentry.mainOrderNumber
cbOrderNumbers.ValueMember = thisentry.mainOrderNumber
Next
Also is their any good free sql to linq tools out their linquer good but its like 60 quid
The problem is that the Distinct() is comparing the entire object being returned, not just the order number.
If you only need the order numbers, changing this line should get you there:
Dim OrderNos = (From r
In Orders.R3Delivery
Where r.mainOrderNumber <> ""
Select r.mainOrderNumber).Distinct().ToList()
If you need the whole object, then it gets more complicated.
I have 2 tables. An asset table that links using a foreign key to a device table.
To get the device_name field of the asset, in linq i would use:
dim device as string = result.device.device_name
The Result object contains the unique record from an earlier linq to entity framework command.
Now I have a need to allow end users to specify their fields they want in a report. I will end up having a string name of the field, so tried using reflection
dim name as string = result.GetType().GetProperty("asset_name").GetValue(result)
This returns the asset_name field so i thought great, i should be able to get the relating foreign table field value.
dim device = result.GetType().GetProperty("device").GetValue(result).GetType.GetProperty("device_name").GetValue(result.device)
This works however i had to specify the object. As i will have other tables linking to the first table, would i have to write additional code to check what object and manually specify? Or am i going into this wrongly? Any help and advice appreciated.
I couldn't find a cleaner solution, so this is how i did it:
dim field as string ="device.device_name"
dim output as string =""
dim subtable as string =""
If field.Contains(".") Then
subtable = field.Substring(0, field.IndexOf("."))
field = field.Substring(field.IndexOf(".") + 1)
End If
If subtable <> "" Then
Select case subtable
Case "device"
If Not IsNothing(result.device.GetType().GetProperty(field)) Then
output = result.device.GetType().GetProperty(field).GetValue(result.device)
End If
End Select
Else
If Not IsNothing(result.GetType().GetProperty(field)) Then
output= result.GetType().GetProperty(field).GetValue(reult)
End If
End If
Return output
I'm trying to query old Access database tables and compare them with SQL Server tables.
They often don't have primary keys, or they have extra fields that had some purpose in the nineties, etc., or the new tables have new fields, etc.
I need to find records - based on a set of fields specified at runtime - that are in one table but not another.
So, I do this kind of query all the time in SQL, when I'm comparing data in different tables:
dim fields_i_care_about as string = "field1, field2, field3"
'This kind of thing gets set by a caller, can be any number of fields, depends on the
'table
dim s as string= ""
dim flds = fields_i_care_about.split(",")
for i as integer = 0 to ubound(flds)
if s > "" then s += " AND "
s += " dysfunctional_database_table." & flds(i) & "=current_database_table." & flds(i)
next
s = "SELECT * from dysfunctional_database_table where not exists (SELECT * from current_database_table WHERE " & s & ")"
====
I'm trying to do this using Linq because it seems like some of the datatype problems with two different database types become less of a headache,
but I'm new to Linq and totally stuck.
I got as far as this:
Put old and new tables into datatables as dt1 and dt2
Dim new_records = _
From new_recs In dt2.AsEnumerable
Where Not ( _
From old_recs In dt1.AsEnumerable Where old_recs(field1) = new_recs(field1) AndAlso old_recs(field2) = new_recs(field2)).Any
Select new_recs
But I can't figure out how to put this part in on the fly -
old_recs(field1) = new_recs(field1) AndAlso old_recs(field2) = new_recs(field2)
So far I've tried:
putting the fields I want to compare and making them a string and just putting that string in as a variable ( I thought I was probably cheating, and I guess I was)
dim str = old_recs(field1) = new_recs(field1) AndAlso old_recs(field2) = new_recs(field2)
From new_recs In dt2.AsEnumerable
Where Not ( _
From old_recs In dt1.AsEnumerable Where str).Any
Select new_recs
It tells me it can't convert a Boolean -
Is there any way to do this without Linq expressions? They seem far more complex than what I'm trying to do here, and they take a lot of code, and also I can't seem to find examples of Expressions where we're comparing two fields in a subquery.
Is there a simpler way? I know I could do the usual EXISTS query using JOIN or IN - in this case I don't need the query to be super fast or anything. And I don't need to use a DataTable or DataSet - I can put the data in some other kind of object.
So I found a lot of sample code that used MethodInfo and reflection and things like that, but I couldn't get any of it to work - these Datarows have a Field method but it requires that you add an (of object) argument before the field name argument and that's tricky to do.
So I'm not sure if this solution is the most efficient way, but at least it works. I'd be interested in finding out whether this way of doing it is efficient and why or why not. It seemed like most people used reflection to do this kind of thing, but I couldn't get that working properly and anyway what I'm trying to do is pretty simple while those methods were pretty complex. I suppose I'm doing Linq with a SQL mindset, but anyway it works.
Dim f As Func(Of DataRow, DataRow, String, Boolean) = Function(d1 As DataRow, d2 As DataRow, s As String)
Dim fields = Split(s, ",")
Dim results As Boolean = True
For k As Integer = 0 To UBound(fields)
Dim obj = DataRowExtensions.Field(Of Object)(d1, fields(k))
Dim obj2 = DataRowExtensions.Field(Of Object)(d2, fields(k))
If obj <> obj2 Then results = False : Exit For
Next
Return results
End Function
Dim new_records = _
From new_recs In dt2.AsEnumerable.AsQueryable()
Where Not ( _
From old_recs In dt1.AsEnumerable.AsQueryable Where f(old_recs, new_recs, id_key)).Any
Select new_recs
Try
Return new_records.CopyToDataTable
Catch ex As Exception
Stop
End Try