How to check in a linq query for null? - c#

I am trying in a linq query to check if one of the fields is null but i get this error whatever i do.
"Non-static method requires a target."
This is my code :
var users = from s in db.Users
where s.DepartmentId == booking.Item.DepartmentId && s.UserEmail != null
select s;
is any way to go through this error and be able to actually check if UserEmail is null?
p.s : i am using asp.net mvc entity framework.

Be sure that the first 2 letters are uppercase (DBNull.Value).
EDIT:
Try to copy your booking item into a local variable.
var departmentId = booking.Item.DepartmentId;
var users = from s in db.Users
where s.DepartmentId == departmentId && s.UserEmail != null
select s;

var users = from s in db.Users
where s.DepartmentId == booking.Item.DepartmentId && s.UserEmail != DbNull.Value
select s;
You need to compare it to DbNull.Value

Related

C# Linq Left Outer Join WHERE clause

I have a linq query where i'm trying to return data if the right Sales table doesn't have a record and also only if the Sales.Fallthrough == false && Sales.Date == null.
This is the base of my query and i've tried many different things with this but can't seem to get it to return the required data. Everything I try only seems to return records if there is no Sales OR they match the WERE caluse but not both.
from cr in efContext.Cases
join si in efContext.Sales on cr.CaseId equals si.CaseId into sicr
from sicr in (from si in sicr
where si == null
select si
).DefaultIfEmpty()
where cr.Withdrawn == false
select new
{
CaseId = cr.CaseId,
PropertyAddress = extension.PropertyAddressTownFormat(cr.PropertyAddress1, cr.PropertyTown),
TargetExchangeDate = sicr.TargetExchangeDate == null ? null : sicr1.TargetExchangeDate,
ActualExchangeDate = sicr.ActualExchangeDate,
}).ToList();
EDIT
Missed out a little information.
Also if there is a record in Sales but does not match WHERE clauses then still return the left side and the right side as if there wasn't a record.
Thanks.
Isn't it just...?
from cr in efContext.Cases
join si in efContext.Sales on cr.CaseId equals si.CaseId into sicr
from s in sicr.DefaultIfEmpty()
select new
{
CaseId = cr.CaseId,
PropertyAddress = extension.PropertyAddressTownFormat(cr.PropertyAddress1, cr.PropertyTown),
TargetExchangeDate = s == null || (s.Fallthrough == false && s.Date == null) ? null : s.TargetExchangeDate,
ActualExchangeDate = s == null || (s.Fallthrough == false && s.Date == null) ? null : s.ActualExchangeDate,
};
Please note that you cannot call to ToList since the query returns an anonymous type.

Order by with condition

I want to get the records with "Restricted" at top.
here Is my query:
var records = (from entry in db.Table1
orderby entry.Always_Prohibited
select new
{
RowID = entry.RowID,
VehicleMake = entry.Make,
VehicleModel = entry.Model,
Restricted = (entry.Always_Prohibited == null || entry.Always_Prohibited == "False") ? "Restricted" : "Not Restricted"
}).ToList();
I tried by Orderby but it is not working because entry.Always_Probibited is a string field.
Please suggest me.
If you have only two values, simply order descending:
from entry in db.Table1
orderby entry.Always_Prohibited descending
If you have more, assign integer values to your strings:
from entry in db.Table1
orderby entry.Always_Prohibited=="A" ? 0 : entry.Always_Prohibited=="B" ? 1 : 2 // and so on
As a side note, strings are a pretty terrible way of storing state in databases. You should redesign it to store it as well defined integers (preferably as foreign keys in master lookup tables, ie strongly typed enums).
User then below give code. It will help to you.
var records = (from entry in db.Table1.AsQueryable();
orderby entry.Always_Prohibited
select new
{
RowID = entry.RowID,
VehicleMake = entry.Make,
VehicleModel = entry.Model,
Restricted = (entry.Always_Prohibited == null || entry.Always_Prohibited == "False") ? "Restricted" : "Not Restricted"
}).ToList();

LINQ and check for !=null

Never used LINQ within C# before until 30 mins ago and am struggling to find an answer to my query online (probably due to my lack of understanding).
I have a simple query
var variableName = from a in tableName.AsEnumerable()
where a.column1 == item1
&& a.column2 == item2
&& a.column3 != null
select a;
The SQL column is defined as an int, null.
When the code encounters a record that is null on the database for column3, the following error is generated "the value for column3 in table <tableName> is DBNull".
Instead of checking for != null, i guess i should be using something else, but have attempted checking for DBNull.Value but the compiler states "Operation != cannot be applied to operands of type int and system.DBNull".
Any ideas?
This looks like a typed dataset, which : yeuch - stop using those, but I digress.
As such, accessing a.column3 will always raise an exception if that value is DBNull. You would need to use the typed-dataset pattern:
&& !c.Iscolumn3Null()
tableName.AsEnumerable() makes the query in-memory, so all table rows are downloaded from DB and the conditions are checked on application.
Try that:
var variableName = from a in tableName
where a.column1 == item1
&& a.column2 == item2
&& a.column3 != null
select a;
It should be translated into an SQL query and download only necessary rows.
Try this..
var variableName = from a in tableName.AsEnumerable()
where a.column1 == item1
&& a.column2 == item2
&& a.column3 != dbnull.value
select a;
try
var variableName = from a in tableName.AsEnumerable()
where a.column1 == item1
&& a.column2 == item2
&& !DBNull.Value.Equals(a.column3)
select a;
edit apparently I need to read up on typed data sets :) and why I should never use them

Searching for text in a database with Entity Framework

I'm writing a UI that allows a someone to lookup users by their first and/or last name. For example, if you typed in "Mike" for the first name and "Jo" for the last name, it would return "Mike Jones", "Mike Johnson" and "Mike Jobs". I use the following LINQ statement for this search:
var users = (from u in context.TPM_USER
where u.LASTNAME.ToLower().Contains(LastName.ToLower())
&& u.FIRSTNAME.ToLower().Contains(FirstName.ToLower())
select u);
(There may or may not be a better way to do a case-insensitive like clause, but this seems to work)
The problem is if the user types in a first or last name, but then leaves the other field empty. If I type in "Mike" for the first name and leave the Last Name field blank, I want to return all Mikes regardless of their last name. The above query returns no results unless both fields are filled in with at least something.
I tried:
var users = (from u in context.TPM_USER
where (LastName == "" || u.LASTNAME.ToLower().Contains(LastName.ToLower()))
&& (FirstName == "" || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()))
select u);
However, I still get no results unless both fields are filled out. I've verified under the debugger that LastName == "" is indeed true.
UPDATE:
I did some more debugging and this is actually an Oracle issue. The query being generated is:
--Replaced the field list with * for brevity
SELECT * FROM TPMDBO.TPM_USER "Extent1"
WHERE (('jones' = '') OR ((INSTR(LOWER("Extent1".LASTNAME), LOWER('jones'))) > 0)) AND (('' = '') OR ((INSTR(LOWER("Extent1".FIRSTNAME), LOWER(''))) > 0))
Which at first glance appears to be correct. However, Oracle does not seem to correctly short-circuit the phrase ('' = ''). In fact, if I do:
select * from TPM_USER where '' = ''
I get zero rows. I'm not enough of an Oracle expert to know how this query should be written, but either way it's an Entity Framework dialect bug.
Just add the predicates conditionally:
var users = from u in context.TPM_USER select u;
if (!string.IsNullOrWhiteSpace(FirstName))
users = users.Where(u => u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()));
if (!string.IsNullOrWhiteSpace(LastName))
users = users.Where(u => u.LASTNAME.ToLower().Contains(LastName.ToLower()));
Or only the LASTNAME predicate as conditional one.
Later addition:
An expression like Where(u => u.FIRSTNAME.ToLower()... is better to be avoided. They cause any indexes on FIRSTNAME to be ignored, because the field value is converted first and then compared (see here for more details).
There's a big chance you don't need these lower-case conversions. Check the database collation of the field. If it's case-insensitive (CI), which it probably is, you don't need these conversions.
Are you sure that FirstName and LastName aren't null?
You might try writing it like this instead...
string LowerFirstName = (FirstName + "").ToLower();
string LowerLastName = (LastName + "").ToLower();
var users = (from u in context.TPM_USER
where (LowerLastName == "" || u.LASTNAME.ToLower().Contains(LowerLastName))
&& (LowerFirstName == "" || u.FIRSTNAME.ToLower().Contains(LowerFirstName))
select u);
FYI, if anyone runs into this issue with Oracle, here's a workaround:
var users = (from u in context.TPM_USER
where (LastName == null|| u.LASTNAME.ToLower().Contains(LastName.ToLower()))
&& (FirstName == null || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()))
select u);
This will get converted to:
'' is null
In SQL, which Oracle interprets as true.
You could simply create a conditional statement around your query:
if (String.IsNullOrWhiteSpace(LastName) && !String.IsNullOrWhiteSpace(FirstName))
{
var users = (from u in context.TPM_USER
where (u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()))
select u);
}
else if (String.IsNullOrWhiteSpace(FirstName) && !String.IsNullOrWhiteSpace(LastName))
{
var users = (from u in context.TPM_USER
where (u.LASTNAME.ToLower().Contains(LastName.ToLower()))
select u);
}
May be you can try checking the length of the search terms to see if it is working in Oracle PL/SQL.
var users = (from u in context.TPM_USER
where ((LastName ?? "").Trim().Length == 0 || u.LASTNAME.ToLower().Contains(LastName.ToLower()))
&& ((FirstName ?? "").Trim().Length == 0 || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()))
select u);

linq - include where parameters

I have a strange question about Linq.
I have this query:
var results = (from p in hotsheetDB.Properties
where p.PCode == pCode
&& p.PropertyStatusID == propertyStatuses
orderby p.PropertyID descending
select new
{
PropertyId = p.PropertyID,
PCode = p.PCode,
PropertyTypeName = p.cfgPropertyType.Name,
FullAddress = p.Address1 + " " + p.Address2,
ZipCode = p.ZipCode.Code,
CityName = p.cfgCity.Name,
LivingSquareFeet = p.LivingSquareFeet,
LotSquareFeet = p.LotSquareFeet,
NumBedrooms = p.NumBedrooms,
NumBathrooms = p.NumBathrooms,
PropertyStatusName = p.cfgPropertyStatuse.Name
});
You notice pCode and propertyStatuses parameters. They are input values from the users. He wants to search by pCode or/and by propertyStatuses.
So, when the user fills in only pCode he wants to return all the records with that pCode having ANY propertyStatuses...well, because propertyStatuses IS in the query but it's null, the query will not return anything (because there is no record with empty(null) propertyStatuses...
Therefore, the question: is there any way to include these where params only whey they have values? (without making separate N queries with all the combination? (I have multiple inputs)
Thanks in advance..
You could change your where clause to make the parts which include null always return true.
For example:
where (pCode == null || p.PCode == pCode)
&& (propertyStatuses == null || p.PropertyStatusID == propertyStatuses)
I'm only guessing here but try:
where p.PCode == pCode &&
(p.PropertyStatusID == null || p.PropertyStatusID == propertyStatuses)

Categories

Resources