The question arose how to implement search in applications. Suppose we have 5 parameters by which it is possible to search for employees: The period of time to get a job (beginning of period, end of period); Name; Surname; Middle name. You can search for any of the parameters (as soon as by name [everything else is ignored], and in full name, and for all parameters taken together). An object of type comes to the service:

public class SearchContext { public DateTime? BeginDate { get; set; } public DateTime? EndDate { get; set; } public string Name { get; set; } public string SecondName { get; set; } public string MiddleName { get; set; } } 

How to correctly search the table for these parameters? As an option, you can pile up ifov type:

  public IEnumerable<Employee> Search(SearchContext searchContext) { if (string.IsNullOrEmpty(searchContext.Name) && string.IsNullOrEmpty(searchContext.SecondName) && string.IsNullOrEmpty(searchContext.MiddleName) && searchContext.BeginDate.HasValue && searchContext.EndDate.HasValue) return _employeeDAO.GetEmployeesByPeriod(searchContext.BeginDate.Value, searchContext.EndDate); //.....продолжаем проверять разные условия } 

The second option is to create some special class of type ExpressionBuilder, then the code will look something like this:

  public IEnumerable<Employee> Search(SearchContext searchContext) { var builder = new ExpressionBuilder<Employee>(); if (!string.IsNullOrEmpty(searchContext.Name)) builder = builder.Property(x => x.Name).AreEquals(searchContext.Name); if (!string.IsNullOrEmpty(searchContext.SecondName)) builder = builder.Property(x => x.SecondName).AreEquals(searchContext.SecondName); var condition = builder.Build(); return _employeeDAO.GetEmployeesByQuery(condition); } 

The second option seems to be more successful as the readability of the method improves. I want to hear the opinion of knowledgeable people.

    1 answer 1

    Vlob option - use LINQ and IQueryable (since the tag is worth it). Or your implementation of the Query Object:

     public IEnumerable<Employee> Search(SearchContext searchContext) { var result = _employeesContext.Employees; // IQueryable<Employee> if (!string.IsNullOrEmpty(searchContext.Name)) { result = result.Where(e => e.Name == searchContext.Name); } // ... return result; } 

    but if s will not go anywhere.

    A more beautiful option is to have separate classes for different conditions.

     public class NameCondition : ICondition { IQueryable<Employee> ApplyTo(IQueryable<Employee> source) { return.Where(e => e.Name == searchContext.Name); } } 

    and instead of SearchContext drag a list of conditions:

     public IEnumerable<Employee> Search(SearchContext searchContext) { var result = _employeesContext.Employees; // IQueryable<Employee> foreach (var condition in searchContext.Conditions) { result = condition.ApplyTo(result); } return result; } 

    In general, everything _employeeDAO on your _employeeDAO - if he can LINQ, then you should use LINQ. If you are not able to - then you will have to invent your own bike (for example, write your LINQ provider, this is quite simple).

    • How then correctly to implement DAO (with EntityFramework)? Otherwise, I usually do just a set of functions like GetEmployeeById (Guid id), GetEmployeesByName (string name), and so on, in the DAO itself I just write something like: context.Employees.Where (x => x.Name == name ) .ToList (); - NEvOl
    • 2
      @SergeyNikolaev is an extensive topic, and there are a lot of opinions on it. from "EF is a ready-made DAO implementation, do not need to overwrite its self-written wrappers" to "make an insulating wrapper, with the type of your repository implementation and unit of work on the basis of their finished EF implementations." I would advise not to complicate, and take the first option :) - PashaPash