使用Dynamic SQL WHERE子句的实体框架搜索功能

时间:2017-01-20 18:03:49

标签: c# entity-framework linq tsql

大家好我在使用动态SQL进行搜索查询,其中我常常附加WHERE& AND条款逐段形成一个陈述,我最近来到下面替代这个,生活是惊人的

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)

现在问题是因为我实现了实体框架,我需要实现与Linq查询相同。我有可空的字节类型和可空的布尔值,我目前无法处理

就像Coalesce我的愚蠢尝试一样 && (s.Floors == deal.Floors.HasValue ? null : s.Floors)

下面的代码与任何结果不匹配

[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);
    } 

表的值类似于

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

我需要的结果是id 1&amp; 2 例如,在前端用户希望仅用“1”填充浴室区域并将场地字段留空

2 个答案:

答案 0 :(得分:1)

您正在测试表中的字段是否等于'deal'属性或字段是否为null而不是这样做:

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

如果你这样做,它应该是等效的查询。

你也可以累积这样做。例如,您可以执行完全匹配的情况:

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)

这可以使得结果查询更有效。通过使用联合使用非完全匹配,可以采用类似的方法。我不知道手边的语法。

答案 1 :(得分:1)

不一样。在您的查询中,您的coalesce位于参数上,然后将记录值作为默认值(如果为空)。在您的c#lambda中,您正在检查参数是否与表值相同,然后检查表值是否为null,但是忽略了参数中为空值的可能性。

实施例

Sql

Department = Coalesce(@Department, Department )

将是

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

这不是你现在所拥有的

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

修改

如果您想复制现在的COALESCE表达式,可以这样写,但我不确定它是否会降低效率/性能。

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