티스토리 뷰

반응형

고객 화면에 검색 조건이 이름, 성별, 직책 등 여러가지가 있는데, Entity Framework에서는 동적으로 where절을 구성할 수 있나? 라는 고민 때문에 검색을 해보니 스택 오버플로우에서 추천하는 기능이 있어서 사용해 보았습니다.

 

C# in a Nutshell - PredicateBuilder (albahari.com)

 

C# in a Nutshell - PredicateBuilder

Extras Dynamically Composing Expression Predicates Suppose you want to write a LINQ to SQL or Entity Framework query that implements a keyword-style search. In other words, a query that returns rows whose description contains some or all of a given set of

www.albahari.com

PredicateBuilder를 이용해서 여러가지 조건을 미리 입력하고 최종적으로 리스트를 조회하면 되도록 되어있습니다. 사용하기도 편하고, 적용하기도 매우 간단하내요.

PredicateBuilder를 사용하기 위해서는 LINQKit nuget package를 설치해야합니다.

linqkit으로 검색하면 4개정도가 검색되며, 그 중에 자신의 프로젝트에 맞는 것을 설치하면 됩니다.

 

UnoContoso.Repository 프로젝트는 Entity Framework 3.1.9를 사용하므로 LinqKit.Microsoft.EntityFrameworkCore 3.0.22를 설치하도록 합니다.

 

기존 검색 방법

원래는 value에 여러개의 검색어를 입력하면 그 검색 단어를 모두 조합을 하는 것이였는데, where에서 오류가 발생해서 1개의 단어에 대해서만 검색하도록 만들어 놓았었습니다.

        public async Task<IEnumerable<Customer>> GetAsync(string value)
        {
            value = value.ToLower();
            //Fix to search only with the first word because it cannot be complicated due to an Entity Framework error.
            string[] parameters = value.Split(' ');

            try
            {
                var customers = await _db.Customers
                    .AsNoTracking()
                    .Where(customer =>
                            customer.FirstName.ToLower().StartsWith(parameters[0]) ||
                            customer.LastName.ToLower().StartsWith(parameters[0]) ||
                            customer.Email.ToLower().StartsWith(parameters[0]) ||
                            customer.Phone.ToLower().StartsWith(parameters[0]) ||
                            customer.Company.ToLower().StartsWith(parameters[0]) ||
                            customer.Address.ToLower().StartsWith(parameters[0]))
                    .ToListAsync();
                return customers;
            }
            catch (Exception ex)
            {
                throw;
            }
        }

PredicateBuilder 적용

        public async Task<IEnumerable<Customer>> GetAsync(string value)
        {
            value = value.ToLower();
            string[] parameters = value.Split(' ');

            try
            {
                //Predicate 생성
                var predicate = PredicateBuilder.New<Customer>();
                //입력된 단어를 이용해서 검색 조건 동적 생성
                foreach (var para in parameters)
                {
                    predicate.And(
                        c =>
                        c.FirstName.ToLower().StartsWith(para) ||
                        c.LastName.ToLower().StartsWith(para) ||
                        c.Email.ToLower().StartsWith(para) ||
                        c.Phone.ToLower().StartsWith(para) ||
                        c.Company.ToLower().StartsWith(para) ||
                        c.Address.Contains(para));
                }
                //AsExpandable() 필수
                return await _db.Customers
                    .AsNoTracking()
                    .AsExpandable()
                    .Where(predicate)
                    .ToListAsync();
            }
            catch (Exception ex)
            {
                throw;
            }
        }

 

적용된 결과

ka와 north가 들어간 레코드만 조회했습니다.

 

PredicateBuilder를 이용하면, 다양한 검색 조건을 만들고, 적용 여부를 if를 통해서 확인한 후 추가하여 사용자가 원하는 결과만을 반환하도록 쉽게 만들 수 있습니다.

반응형
댓글