[c#] 조건부 Linq 쿼리

우리는 로그 뷰어를 만들고 있습니다. 사용에는 사용자, 심각도 등을 기준으로 필터링 할 수있는 옵션이 있습니다. SQL 날에는 쿼리 문자열에 추가했지만 Linq를 사용하여 수행하고 싶습니다. 조건부로 where 절을 추가하려면 어떻게해야합니까?



답변

특정 기준이 통과 된 경우에만 필터링하려면 다음과 같이하십시오.

var logs = from log in context.Logs
           select log;

if (filterBySeverity)
    logs = logs.Where(p => p.Severity == severity);

if (filterByUser)
    logs = logs.Where(p => p.User == user);

이렇게하면 식 트리가 원하는대로 정확하게 될 수 있습니다. 이렇게하면 생성 된 SQL이 정확히 필요한 것입니다.


답변

목록 / 배열을 기준으로 필터링해야하는 경우 다음을 사용하십시오.

    public List<Data> GetData(List<string> Numbers, List<string> Letters)
    {
        if (Numbers == null)
            Numbers = new List<string>();

        if (Letters == null)
            Letters = new List<string>();

        var q = from d in database.table
                where (Numbers.Count == 0 || Numbers.Contains(d.Number))
                where (Letters.Count == 0 || Letters.Contains(d.Letter))
                select new Data
                {
                    Number = d.Number,
                    Letter = d.Letter,
                };
        return q.ToList();

    }


답변

Daren과 비슷한 대답을 사용했지만 IQueryable 인터페이스를 사용하여 끝냈습니다.

IQueryable<Log> matches = m_Locator.Logs;

// Users filter
if (usersFilter)
    matches = matches.Where(l => l.UserName == comboBoxUsers.Text);

 // Severity filter
 if (severityFilter)
     matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);

 Logs = (from log in matches
         orderby log.EventTime descending
         select log).ToList();

데이터베이스에 도달하기 전에 쿼리를 작성합니다. 이 명령은 마지막에 .ToList ()까지 실행되지 않습니다.


답변

조건부 linq에 관해서는 필터와 파이프 패턴을 매우 좋아합니다.
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/

기본적으로 IQueryable 및 매개 변수를 사용하는 각 필터 케이스에 대한 확장 메서드를 만듭니다.

public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
    return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}


답변

유창한 표현 중에 LINQ를 조건부로 활성화 할 수 있도록 확장 메서드로이 문제를 해결했습니다. 이렇게하면 if문으로 식을 분리 할 필요가 없습니다 .

.If() 확장 방법 :

public static IQueryable<TSource> If<TSource>(
        this IQueryable<TSource> source,
        bool condition,
        Func<IQueryable<TSource>, IQueryable<TSource>> branch)
    {
        return condition ? branch(source) : source;
    }

이를 통해 다음을 수행 할 수 있습니다.

return context.Logs
     .If(filterBySeverity, q => q.Where(p => p.Severity == severity))
     .If(filterByUser, q => q.Where(p => p.User == user))
     .ToList();

다음 IEnumerable<T>은 대부분의 다른 LINQ 식을 처리 하는 버전 도 있습니다 .

public static IEnumerable<TSource> If<TSource>(
    this IEnumerable<TSource> source,
    bool condition,
    Func<IEnumerable<TSource>, IEnumerable<TSource>> branch)
    {
        return condition ? branch(source) : source;
    }


답변

또 다른 옵션은 여기에서 설명하는 PredicateBuilder와 같은 것을 사용하는 것 입니다. 다음과 같은 코드를 작성할 수 있습니다.

var newKids  = Product.ContainsInDescription ("BlackBerry", "iPhone");

var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
                  .And (Product.IsSelling());

var query = from p in Data.Products.Where (newKids.Or (classics))
            select p;

Linq 2 SQL에서만 작동합니다. EntityFramework는이 메서드가 작동하는 데 필요한 Expression.Invoke를 구현하지 않습니다. 여기 에이 문제에 대한 질문이 있습니다 .


답변

이렇게 :

bool lastNameSearch = true/false; // depending if they want to search by last name,

where성명서에 이것을 가지고 :

where (lastNameSearch && name.LastNameSearch == "smith")

즉, 최종 쿼리가 생성 될 때, 경우 lastNameSearch입니다 false쿼리가 완전히 성 검색에 어떤 SQL을 생략합니다.