NullReference exception when using LINQ Contains with Entity Framework - linq

I'm working on a project where I'm converting Linq to SQL (which I admittedly very poorly understand) to Linq to Entity and have ran into an odd situation. The code below correctly returns results when evaluated against a class generated in the Linq to SQL designer but does not work when run against an Entity Framework entity. Specifically if any of the properties in the Or clauses are null, the process breaks with a Null Reference exception. I've tried techniques to check for null property and then say, pass a value I know can't be in the SearchTerm to short circuit around this but they just result in this LINQ returning all results from the entity in a way that I don't really understand either.
Return (From values In Location.getData _
Where (values.LocName.Contains(SearchTerm) _
Or values.Address.Contains(SearchTerm) _
Or values.Address2.Contains(SearchTerm) _
Or values.City.Contains(SearchTerm) _
Or values.State.Contains(SearchTerm) _
Or values.QIM.Contains(SearchTerm) _
Or values.MacID.Contains(SearchTerm) _
Or values.Phone.Contains(SearchTerm) _
Or values.PrimServ.Contains(SearchTerm) _
Or values.Zip.Contains(SearchTerm) _
Or values.Area.Contains(SearchTerm) _
Or values.Type.Contains(SearchTerm)
) And (values.Status <> "Closed" Or status_parm = "Closed")
Select values)
As you can probably guess the getData method on the entity class Location is basically using DbContext.SqlQuery to construct a query into the database and then this LINQ is being used to filter the results. I'm aware of several issues with this that make it less than ideal, but there are reasons it was written this way before I started the conversion that aren't easily changed.

E.g.
Where (values.LocName IsNot Nothing AndAlso values.LocName.Contains(SearchTerm)) OrElse
(values.Address IsNot Nothing AndAlso values.Address.Contains(SearchTerm))

So the answer I finally got working was to use ToLower
SearchTerm = SearchTerm.ToLower
Return (From values In Location.getData _
Where (values.LocName IsNot Nothing And Also values.LocName.ToLower.Contains(SearchTerm)
I would still like to understand two things:
Why is a check for null required when using LINQ to Entity where in LINQ to SQL it runs without issue and never hits a NullReference exception?
Why is LINQ's .Contains not case sensitive in LINQ to SQL but it is here? I've verified with 100% certainty this same code using LINQ to SQL does not throw NullReference exceptions ever, and does not require dealing with .Contains as a case sensitive function (so any casing of the SearchTerm will match to any casing of the result implicitly.)

Related

Linq to DataSet query isn't returning expected EnumerableRowCollection<DataRow>

dtbl isn't a strongly typed DataTable, but all these nonetheless work fine (so namespaces and references appear to be ok)
EnumerableRowCollection<DataRow> a = dtbl.AsEnumerable();
DataView b = dtbl.AsDataView();
IEnumerable<DataRow> c = from y in dtbl.AsEnumerable() select y;
however, both these yield:
"Cannot implicitly convert IEnumerable to EnumerableRowCollection"
EnumerableRowCollection<DataRow> d = from y in dtbl.AsEnumerable() select y;
EnumerableRowCollection<DataRow> e = dtbl.AsEnumerable().Select(y=>y);
the error makes sense, but queries returning EnumerableRowCollection are shown in
MSDN example http://msdn.microsoft.com/en-us/library/bb669080(v=vs.110).aspx and here on
stackoverflow without apparent hiccup
this is a showstopper, so a solution would be very welcome, as I need to get to:
DataView view = (query performing filter and sort on dtbl).AsDataView();
I can't reproduce this with VS 2012 and .Net 4.5, but a work-around could be to bypass the syntactic sugar of extension methods and use the Select method directly off the static class in which it is defined:
EnumerableRowCollectionExtensions.Select(dtbl.AsEnumerable(), d => d)
See EnumerableRowCollectionExtensions Class.
SOLVED: it was an interfering extension method; I defined a list of "pass-though" extensions (Select, OrderBy, etc) to allow functions in other source files to avoid "using System.Linq", as well as allowing all Linq calls to be quickly found by reference.
Turns out there are undocumented (and apparently inaccessible) versions of the extension methods like EnumerableRowCollection.Select<>() that get hidden by the pass-throughs, and that are defined in an extension class that so far I can't find.
Anyway, I can get there from here by either finding the extension class, or yanking the pass-throughs.

DbLimitExpression requires a collection argument

Does anyone have the faintest idea what this error means please and how to resolve it? All my research is drawing a blank, I can see how to set it on MSDN but it doesn't explain it in a way that explains to me what the issue is. If I remove some of my LINQ queries to set viewbag items then it seems to resolve it but the moment I set new ones and pass them into my view to generate a mail for MVCMailer it comes back. Not sure if its a viewbag issue or simply that I am calling too many linq queries to generate them to pass to the view.
I am very stuck (again)..........
Cheers,
Steve.
DbLimitExpression requires a collection argument.
Parameter name: argument
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: DbLimitExpression requires a collection argument.
Parameter name: argument
An example of the code is:
var VBSalutation = from A in context.Salutations
where A.SalutationId == policytransaction.SalutationId
select A.SalutationName;
ViewBag.Salutation = VBSalutation.FirstOrDefault();
This is repeated for various parameters and then passed to the view.
Well, I faced a similar problem and solved it. Problem was in WHERE clause: data type of left side equal operator (=) sign was not matching with data type of right side. So in your scenario:
where A.SalutationId == policytransaction.SalutationId
SalutationID of A might be an INT and SalutationId of policytransaction might be a string (This is how it was in my case).
I solved it by assigning policytransaction.SalutationId to an Int variable and using it:
int myIntVariable = Convert.ToInt16(policytransaction.SalutationId);
...//some code here
where A.SalutationId == myIntVariable;
Please also note that you cannot directly cast your variables directly in Linq else you'll get an error "LINQ to Entities does not recognize the method". You'll have to use a temp variable and then apply the where clause.
Try ViewBag.Salutation = VBSalutation.SingleOrDefault();

passing parameter to Dataenvironment visual basic

HI,
I am working on Visual Basic DataEnvironment I have written SQL command but i need to pass some parameter from one of my form object.
I have tried this
SELECT * from user WHERE userid= form1.textbox1.text
but it doesn't seems to be work. Any Idea how to pass parameter.
I would suggest performing a filter on the recordset inside your DataEnviroment instead placing the WHERE clause where your SQL statement is defined.
With DataEnvironment1.rsDataTable
.Filter = "UserID = " & textbox1.text
End With
Please check out the following links. I hope this helps.
http://msdn.microsoft.com/en-us/library/aa231245(v=vs.60).aspx
http://pages.cpsc.ucalgary.ca/~saul/vb_examples/tutorial4/index.html
Also, if possible I would recommend using ADO instead of the DataEnvironment.

"could not instantiate" NHibernate.QueryException Raise By Combined Linq Query

Executing the following NHibernate.Linq statement raises a "could not instantiate: Reservation001.Services.ReservationDto" NHibernate.QueryException containing an inner InvalidCast exception ("Object must implement IConvertible."):
var inOneStep = (from r in session.Linq<Models.ReservationHeader>()
select new ReservationDto(r.Current));
return inOneStep;
However, after splitting the above into two queries, with ToList() called on the results of the first, the code executes fine.
var step1 = (from r in session.Linq<Models.ReservationHeader>()
select r).ToList();
var step2 = from z in step1
select new ReservationDto(z.Current);
return step2;
Why does the single statement version raise an exception?
Thank you,
Ben
The reason that the first one does not work is because the whole query is getting sent to NHibernate, and (as the exception tells you) NHibernate expects something with ReservationDto to be IConvertible.
The two step process avoids this error, because by calling "ToList()" you cause the query to execute in NHibernate immediately without involving ReservationDto, and returning an object collection. Your second step is then simply operating on an object collection, and since NHibernate is no longer involved, you avoid the error.
In general, Linq uses delayed execution, with a few functions (such as ToList() ) forcing immediate evaluation. See http://devlicio.us/blogs/derik_whittaker/archive/2008/04/07/linq-and-delayed-execution.aspx

ADODB Recordset.Recordcount corruption with oracle (ASP)

For some unknown reason, when I try to read the RecordCount property from an ADODB.Recordset object in ASP it causes strange data corruption that doesn't appear to follow any particular pattern that I can find. I'm using ASP to connect to an Oracle 10g database. The following is the code I am using.
c_objRS.Open strSql, objPage.objCn, adOpenStatic, adLockReadOnly, adCmdText
DB_ReadListCount = c_objRS.RecordCount
For some reason, some CLOB objects that are read from this recordset return the value null ONLY if I call c_objRS.RecordCount. If I do not call it, or if I call c_objRS.Close then c_objRS.Open, then it works just fine. Also c_objRS.Requery appears to fix the issue.
I don't really want to use these methods at the moment because I fear some level of data corruption via opening and closing the result set and I do not want to re-run another query since the table in question can eventually become quite huge.
I'm currently using ODAC 11.1.0.6.21
Any help would be much appreciated!
Try MoveNext or MoveLast then use MoveFirst. This might help.
Try this:
If Not c_objRS.EOF Then
c_objRS.MoveNext
DB_ReadListCount = objRS.RecordCount
Else
DB_ReadListCount = 0
End If

Resources