Why does EF return 0 results for a search for NULL - entity-framework-6

My database has a bit column which is nullable, called IsPerpetual.
I'm trying to retrieve a collection where this column is null. I am failing to do so
My code is very simple
var dc = new DalCf.Entities(ProgramState.ConnectionString);
var results = dc.Main.Where(a => a.IsPerpetual == null);
var testForKnownEntryWithNull = dc.Main.Single(a => a.Id == 24589);
var isNull = testForKnownEntryWithNull.IsPerpetual == null; //isNull is true ?!?
The value results returns a collection with 0 items.
The value testForKnownEntryWithNull has a property called IsPerpetual which is set to null
The value isNull is true.
Am I supposed to be querying EF 6 in a different way? I am totally bewildered with this.
I'm running this code in a unit test (MS Tests) in VS2019 on .NET Framework 4.7.2

Related

Linq Get Latest Date Query

I am trying to get the latest date based on my controller below but I was hit with this error :
"Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery1[<>f__AnonymousType201[System.Nullable`1[System.DateTime]]]' to type 'System.IConvertible'."
var latestDt = from n in db.Books
where n.id == id
select new { Date = n.dtBookBorrowed};
DateTime dtPlus1Year = Convert.ToDateTime(latestDt);
May I know how do I get just the column latestDate in linq?
You can try this to get list of date order by latest insert to db.
var latestDt = db.Books.Where(n => n.id == id).OrderByDescending(x => x.dtBookBorrowed).Select(x => x.dtBookBorrowed).ToList();
I think if you use
DateTime.Parse(item.dateAsString)
your problem should be solved.
The LINQ query expression you've defined returns a collection of anonymous object with property Date despite there might be only one record match as ID was meant to be unique.
In your case we only need the target field that can be parsed as DateTime and therefore an alternative in fluent syntax would be as following:-
var book = db.Books.SingleOrDefault(book => book.id == id); // gets matching book otherwise null
if (book != null)
{
var borrowedDate = Convert.ToDateTime(book.dtBookBorrowed);
}
Otherwise if you would like to understand more about the behaviour with query syntax which may return multiple results, you may simplify as following which returns collection of DateTime object (i.e. IEnumerable) instead:-
IEnumerable<DateTime> borrowedDates =
from n in db.Books
where n.id == id
select Convert.ToDateTime(n.dtBookBorrowed);

LINQ query with omitted user input

so I have a form with several fields which are criteria for searching in a database.
I want to formulate a query using LINQ like so:
var Coll = (from obj in table where value1 = criteria1 && value2 = criteria2...)
and so on.
My problem is, I don't want to write it using If statements to check if every field has been filled in, nor do I want to make separate methods for the various search cases (criteria 1 and criteria 5 input; criteria 2 and criteria 3 input ... etc.)
So my question is: How can I achieve this without writing an excessive amount of code? If I just write in the query with comparison, will it screw up the return values if the user inputs only SOME values?
Thanks for your help.
Yes, it will screw up.
I would go with the ifs, I don't see what's wrong with them:
var query = table;
if(criteria1 != null)
query = query.Where(x => x.Value1 == criteria1);
if(criteria2 != null)
query = query.Where(x => x.Value2 == criteria2);
If you have a lot of criteria you could use expressions, a dictionary and a loop to cut down on the repetitive code.
In an ASP.NET MVC app, chances are your user input is coming from a form which is being POSTed to your server. In that case, you can make use of strongly-typed views, using a viewmodel with [Required] on the criteria that MUST be provided. Then you wrap your method in if (ModelState.IsValid) { ... } and you've excluded all the cases where the user hasn't given you something they need.
Beyond that, if you can collect your criteria into a list, you can filter it. So, you could do something like this:
filterBy = userValues.Where(v => v != null);
var Coll = (from obj in table where filterBy.Contains(value1) select obj);
You can make this more complex by having a Dictionary (or Lookup for non-unique keys) that contains a user-entered value along with some label (an enum, perhaps) that tells you which field they're filtering by, and then you can group them by that label to separate out the filters for each field, and then filter as above. You could even have a custom SearchFilter object that contains other info, so you can have filters with AND, NOT and OR conditions...
Failing that, you can remember that until you trigger evaluation of an IQueryable, it doesn't hit the database, so you can just do this:
var Coll = (from obj in table where value1 == requiredCriteria select obj);
if(criteria1 != null)
{
query = query.Where(x => x.Value1 == criteria1);
}
//etc...
if(criteria5 != null)
{
query = query.Where(x => x.Value5 == criteria5);
}
return query.ToList();
That first line applies any criteria that MUST be there; if there aren't any mandatory ones then it could just be var Coll = table;.
That will add any criteria that are provided will be applied, any that aren't will be ignored, you catch all the possible combinations, and only one query is made at the end when you .ToList() it.
As I understand of your question you want to centralize multiple if for the sake of readability; if I were right the following would be one of some possible solutions
Func<object, object, bool> CheckValueWithAnd = (x, y) => x == null ? true : x==y;
var query = from obj in table
where CheckValue(obj.value1, criteria1) &&
CheckValue(obj.value2, criteria2) &&
...
select obj;
It ls flexible because in different situations or scenarios you can change the function in the way that fulfill your expectation and you do not need to have multiple if.
If you want to use OR operand in your expression you need to have second function
Func<object, object, bool> CheckValueWithOr = (x, y) => x == null ? false : x==y;

Mvc Telerik grid With large database

I am using telerik mvc grid in my mvc project , my table have around 1 Million records. My grid taking too much time to load.
This is my Query
//
var bib = (from a in db.Bibs
join inf in db.InfoTypes
on a.InfoTypeId equals inf.Id
where a.Status == "A"
select new BibViewModel
{
Id = a.Id,
Type = inf.Type,
InfoType = inf.Description,
Title = (from asd in db.BibContents where asd.BibId == a.Id && asd.TagNo == "245" && asd.Sfld == "a" select asd.Value).FirstOrDefault(),
Author = (from asd in db.BibContents where asd.BibId == a.Id && asd.TagNo == "100" && asd.Sfld == "a" select asd.Value).FirstOrDefault(),
CatalogueDate = a.CatalogDate,
Contents = "",
CreatedOn = a.CreatedOn,
ItemRelation = db.Items.Any(item => item.BibId == a.Id),
IssueRelation = db.Issues.Any(item => item.BibId == a.Id),
});
return View(new GridModel(bib.OrderByDescending(x => x.CreatedOn).Tolist()));
ToList() actually invokes the query, so if calling ToList() is taking too long, that means the issue is with the query.
In LINQ, you can use paging like in the following post; the idea is to use Skip and Take to skip X records, and only take Y records, as in:
var results = (from .. select ..).Skip(X).Take(Y)
With 1M records, I would highly suggest replacing it with a stored procedure, which will be much, much faster for what you are trying to do. Consider a custom pagination approach, which works very well for me with large result sets:
http://www.neiland.net/blog/article/dynamic-paging-in-sql-server-stored-procedures/
http://www.beansoftware.com/ASP.NET-Tutorials/Paging-Stored-Procedures.aspx
http://www.sqlpointers.com/2009/10/custom-sorting-and-paging-in-sql-server.html
T-SQL stored procedure with sorting and paging enabled not working properly
If you can't use stored procedures, reading this will help understand what needs to be accomplished with pagination. With LINQ, you'll want to examine the SQL being generated to see where you also can fine-tune the query, either using SQL profiler, or LINQPad.

Cannot convert anonymous type to int - compoiled linq to sql query

I'm trying to do a compiled query but I just want it to return an int
public Func<DataContext, DateTime, int>
GetNextTourNo = CompiledQuery.Compile((DataContext db, DateTime day) => ((from b in db.GetTable<BookingType>()
where b.RecordType == "H" && b.TourStartDateTime.Value.Date == day.Date
orderby b.TourID descending
select new { nextID = b.TourID +1 }).Single()));
You could just return nextID property from selected single anonymous object
select new { nextID = b.TourID +1 }).Single().nextID
Can you provide a bit more information on the anonymous type and the context of the compiled query?
Also if you are using the query directly in linq to Entity the date comparison will not work. Entity Functions need to be used for this. This could cause the invalid return.

Linq with EF dynamic search

I am using EF 3.5 with MVC.
I want to made a search page, has some fields for criteria like date, int etc.
What is the way in linq to entities to filter the result dynamically.
If there are one parameter we can use
.where(a=>a.id==1)
but many combination with optional param how can i load results and then pass to model.
EF 3.5? Anyway...
You can append search criteria over an ObjectQuery, ObjectSet or IQueryable and chain them based on which search criteria is useful.
public SearchMyThings( string a, string b, int c )
{
var mywidgets = ObjectContext.CreateObjectSet<Widget>();
//or the EF 1.0 version CreateSet?
if( !a.IsNullOrEmpty )
mywidgets = mywidgets.Where( w => w.AProperty == a );
if( !b.IsNullOrEmpty )
mywidgets = mywidgets.Where( w => w.BProperty == b );
if( c > 0 )
mywidgets = mywidgets.Where( c => c.CProperty == c );
}
If you need a string based approach you can always use the overloads of ObjectQuery.Where("esql") to dynamically construct some eql and passing that along.
If you need MORE control over the strings and aren't afraid of complexity you could give Dynamic Linq a try.

Resources