Linq to SQL "(값 목록)에서 [열] 위치"수행 방법


101

ID 목록을 가져 오는 함수가 있으며 ID와 관련된 설명과 일치하는 목록을 반환해야합니다. 예 :

public class CodeData
{
    string CodeId {get; set;}
    string Description {get; set;}
}

public List<CodeData> GetCodeDescriptionList(List<string> codeIDs)
    //Given the list of institution codes, return a list of CodeData
    //having the given CodeIds
}

따라서 직접 SQL을 생성하는 경우 다음과 같이 간단히 수행합니다 (in 절에 codeIds 인수의 모든 값이 포함됨).

Select CodeId, Description FROM CodeTable WHERE CodeId IN ('1a','2b','3')

Linq to Sql에서 "IN"절에 해당하는 것을 찾을 수 없습니다. 지금까지 찾은 것 중 최고 (작동하지 않음)는 다음과 같습니다.

 var foo = from codeData in channel.AsQueryable<CodeData>()
           where codeData.CodeId == "1" || codeData.CodeId == "2"
           select codeData;

문제는 linq to sql에 대한 "OR"절 목록을 동적으로 생성 할 수 없다는 것입니다. 왜냐하면 그것들은 컴파일 타임에 설정되기 때문입니다.

Linq to Sql을 사용하여 동적 값 목록에 열이 있는지 확인하는 where 절을 어떻게 수행합니까?

답변:


159

사용하다

where list.Contains(item.Property)

또는 귀하의 경우 :

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codeIDs.Contains(codeData.CodeId)
          select codeData;

그러나 점 표기법으로하는 것이 좋습니다.

var foo = channel.AsQueryable<CodeData>()
                 .Where(codeData => codeIDs.Contains(codeData.CodeId));

CodeId가 Integer 인 경우 사용하는 방법 ??
Kiran Solkar

2
@KiranSolkar : 그렇다면 아마도 codeIDsa List<int>일 것이고, 모두 괜찮을 것입니다.
Jon Skeet

@JonSkeet 대소 문자를 구분하지 않습니까? codeIDs가 대문자 문자열 목록이고 codeData.codeId가 소문자 문자열이면 실패합니다.
PersyJack

@PersyJack : 대소 문자를 구분하지 않아야한다는 질문에 아무것도 없었습니다. 그럴 것인지 여부에 관해서는 LINQ to SQL이 기본적으로 대 / 소문자 구분을 적용하는지 또는 db 설정이이를 제어하도록 허용하는지 기억할 수 없습니다.
Jon Skeet

1
@PersyJack LINQ to SQL은 T-SQL 쿼리를 생성 한 다음 대소 문자 구분을위한 데이터베이스 설정을 사용하여 SQL Server에서 실행됩니다. 주의하지 않고 쿼리 결과를 구체화하더라도 메모리 내 개체에 LINQ를 적용하기 전에 대 / 소문자 구분이 일치하지 않는 결과를 겪을 수 있습니다.
Zarepheth

26

다음을 사용할 수도 있습니다.

List<int> codes = new List<int>();

codes.add(1);
codes.add(2);

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codes.Any(code => codeData.CodeID.Equals(code))
          select codeData;

1
나는 .Contains ()를 지원하지 않습니다 IQToolkit 우리의 구현 때문에 이것을 사용했다
DJ 밴 Wyk

1

나는 Jon Skeet의 답변에서 방법을 사용하고 있었지만 Concat. 이 Concat방법은 제한된 테스트에서 약간 더 잘 수행되었지만 번거롭고 아마도 Contains. 어느 쪽이든 관심이있는 사람이 있다면 다음과 같은 또 다른 옵션이 있습니다.

방법

// Given an array of id's
var ids = new Guid[] { ... };

// and a DataContext
var dc = new MyDataContext();

// start the queryable
var query = (
    from thing in dc.Things
    where thing.Id == ids[ 0 ]
    select thing 
);

// then, for each other id
for( var i = 1; i < ids.Count(); i++ ) {
    // select that thing and concat to queryable
    query.Concat(
        from thing in dc.Things
        where thing.Id == ids[ i ]
        select thing
    );
}

성능 테스트

이것은 원격으로 과학적이지 않았습니다. 데이터베이스 구조와 목록에 포함 된 ID의 수가 상당한 영향을 미칠 것이라고 생각합니다.

각각 100 번의 시도를 수행 Concat하고 Contains각 시도가 무작위 기본 키 목록에 지정된 25 개의 행을 선택 하는 테스트를 설정했습니다 . 나는 이것을 약 12 ​​번 실행했고, 대부분의 경우 Concat방법이 5-10 % 더 빨리 나왔지만 한 번은 Contains방법이 smidgen에 의해 이겼습니다.


0
 var filterTransNos = (from so in db.SalesOrderDetails
                    where  ItemDescription.Contains(ItemDescription)
                            select new { so.TransNo }).AsEnumerable();    


listreceipt = listreceipt.Where(p => filterTransNos.Any(p2 => p2.TransNo == p.TransNo)).ToList();

-1

HashSet을 사용하여 수행하는 방법은 다음과 같습니다.

        HashSet<String> hs = new HashSet<string>(new String[] { "Pluto", "Earth", "Neptune" });
        String[] arr =
        {
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            // etc.
        };
        ICollection<String> coll = arr;

        String[] arrStrFiltered = coll.Where(str => hs.Contains(str)).ToArray();

HashSet은 기본적으로 거의 O (1)이므로 복잡성은 O (n)으로 유지됩니다.


이것은 LINQ-to-SQL에 관한 것입니다. 이러한 LINQ-to-objects 고려 사항은 적용되지 않습니다.
Gert Arnold

ICollection은 LINQ-SQL에서도 올 수 있습니다. 이것은 일반적인 방법입니다
MG

문제는 올바른 SQL로 변환되는 표현식을 작성하는 방법에 관한 것입니다. 그것은 지역 컬렉션을 검색하는 방법과 관련이 없습니다. 당신의 대답은 이러한 구별을 인식하지 못하는 미래의 독자들만 속일 것입니다.
Gert Arnold
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.