简体   繁体   中英

Entity framework LINQ with value OR null

I have the following EF linq query to get all the employess or specific employee, in case if empId has value.

But the EF is not generating the expected query and it ignores OR condition always

from employee 
where employee.DepartmentId == depId && ((employee.Id == empId) || (employee.Id == null))
.ToList()

Expected Query

SELECT * FROM Employee
WHERE DepartmentId = @DepId AND (Id=@empId OR Id IS NULL)

Generated Query by EF when value is passed

SELECT * FROM Employee
WHERE DepartmentId = @DepId AND (Id=@empId)

Generated Query by EF when value is null

SELECT * FROM Employee
WHERE DepartmentId = @DepId AND (Id IS NULL)

Note: No Employee record has Id value NULL and it returns 0 instead of all employees

How to write linq for this Id=@empId OR Id IS NULL ?

You say this is your expected query:

SELECT * FROM Employee
WHERE DepartmentId = @DepId AND (Id=@empId OR Id IS NULL)

but i'm pretty sure that it is not, because the Id is never null (what you also say in your Note ) because it is the primary key of that table. You actually mean this query:

SELECT * FROM Employee
WHERE DepartmentId = @DepId AND (Id=@empId OR @empId IS NULL)

so you want to bypass the check and return all records if the parameter is NULL . Note that this is not the best way performance wise. You should use a query without filter when you don't want to filter by Id . I'm afraid this will not produce the most efficient query plan. I'd use this:

IQueryable<Employee> allDepartmentEmployees = 
    from employee in ...
    where employee.DepartmentId == depId;
    select employee;

if(empId.HasValue) // presuming it's a nullable type
{
    allDepartmentEmployees = allDepartmentEmployees.Where(e => e.Id == empId.Value);     
}

List<Employee> employeeList = allDepartmentEmployees.ToList();

So only filter if the parameter is given. Then this will only return one record.

The LINQ to SQL translation simplified your query logic. They are functionally equivalent.

You should not try to write LINQ in a way that it generates a specific SQL you expect. You are writing LINQ to do a specific operation. If the resulting query does not match your expectation, try to understand why.

When your comparison is (Id=@empId OR Id IS NULL)

  • If @empId is always NULL, then (Id IS NULL) is a functionally equivalent simplification
  • If @empId is a value or may be null then (Id=@empId) is a functionally equivalent simplification

You did not say which DB / DB driver you use with Entity Framework, but you can verify that comparing against NULL is always false:

SELECT CASE WHEN NULL = NULL THEN 1 ELSE 0 END

MS SQL Server returns 0 for this query. So NULL is not equal to NULL.

Database Engines typically interpret and handle NULL a bit differently than C# does null. NULL is unknown rather than unset . In MS SQL Server IS NULL is used to compare against NULL rather than = , != or <> .

For MS SQL Server see NULL and UNKNOWN

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM