简体   繁体   中英

Entity Framework Search functionality with Dynamic SQL WHERE clause

hi guys i was using Dynamic SQL for search queries where i used to attach WHERE & AND clause piece by piece and form a statement, i recently came to below alternate for this, and life was amazing

cool alternates of Dynamic WHERE-Clause

Select * From tblEmployees 
where EmployeeName = Coalesce(@EmployeeName, EmployeeName) AND
Department = Coalesce(@Department, Department ) AND
Designation = Coalesce(@Designation, Designation) AND
JoiningDate >= Coalesce(@StartDate, JoiningDate) AND 
JoiningDate <= Coalesce(@EndDate, JoiningDate) AND
Salary >= Coalesce(@Salary, Salary)

now the issue is since i implemented entity framework i need to achieve same with Linq queries. i have nullable Byte type and nullable boolean which i am currently unable to handle

just like Coalesce my stupid attempt was && (s.Floors == deal.Floors.HasValue ? null : s.Floors)

below code not matching any results

[HttpPost]
        public ActionResult Results(Deal deal, bool exactMatch)
    {
        List<Deal> deals;

        if (exactMatch)
        {
            deals = dataBase.Deals.Where(s =>
               (s.OwnerName.Contains(deal.OwnerName) || s.OwnerName == null)
            && (s.Rooms == deal.Rooms || s.Rooms == null)
            && (s.BathRooms == deal.BathRooms || s.BathRooms == null)
            && (s.Floors == deal.Floors || s.Floors == null)
            && (s.Builtin == deal.Builtin || s.Builtin == null)
            && (s.Kitchens == deal.Kitchens || s.Kitchens == null)
            && (s.DoubleUnit == deal.DoubleUnit || s.DoubleUnit == null)
            && (s.Corner == deal.Corner || s.Corner == null)
            && (s.Remarks.Contains(deal.Remarks) || s.Remarks == null)
            ).ToList();
        }
        else
        {
            deals = dataBase.Deals.Where(s =>
               (s.OwnerName.Contains(deal.OwnerName) || s.OwnerName == null)
            || (s.Rooms == deal.Rooms || s.Rooms == null)
            || (s.BathRooms == deal.BathRooms || s.BathRooms == null)
            || (s.Floors == deal.Floors || s.Floors == null)
            || (s.Builtin == deal.Builtin || s.Builtin == null)
            || (s.Kitchens == deal.Kitchens || s.Kitchens == null)
            || (s.DoubleUnit == deal.DoubleUnit || s.DoubleUnit == null)
            || (s.Corner == deal.Corner || s.Corner == null)
            || (s.Remarks.Contains(deal.Remarks) || s.Remarks == null)
            ).ToList();
        }

        return View(deals);
    } 

table has values like

id Bathroom Floors
1   1        2
2   1        4
3   2        6
4   3        1

i need results which has id 1 & 2 for instance in front end user want to only fill bathroom field with "1" and leave floor field empty

You are testing whether the field in the table equals the 'deal' property or the field is null rather than doing this:

s.Remarks.Contains(deal.Remarks) || deal.Remarks == null

If you do this, it should be the equivalent query.

You can do this cumulatively too. For example with the exact match case you can do:

deals = dataBase.Deals;
if (deal.OwnerName != null)
   deals = deals.Where(s => s.OwnerName.Contains(deal.OwnerName));

if (deal.Rooms != null)
  deals = deals.Where(s => s.Rooms == deal.Rooms)

That can make the resulting query more efficient. There's a similar way to do this with the non exact match through using unions. I don't know the syntax off hand.

Not really the same. In your query your coalesce is on the parameter then taking the record value as the default if it is null. In your c# lambda you are checking if the parameter is the same as the table value and then checking if the table value is null but that omits the possibility of having a null value in the parameter.

Example

Sql

Department = Coalesce(@Department, Department )

would be

(s.Department == deal.Department || deal.Department == null)

not this which is what you have now

(s.Department == deal.Department || s.Department == null)

Edit

If you wanted to duplicate the COALESCE expression you have now you could write it this way although I am not sure if it would decrease efficiency / performance.

(s.Department == (deal.Department ?? s.Department))

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