Contains()를 사용할 때 2100 매개 변수 제한(SQL Server)을 초과하는 경우
from f in CUSTOMERS
where depts.Contains(f.DEPT_ID)
select f.NAME
depts
목록입니다(IEnumerable<int>
부서 ID의 )
이 쿼리는 큰 목록(예: 약 3000개의 디프티 ID)을 통과할 때까지 잘 작동합니다.그러면 다음 오류가 발생합니다.
수신 TDS(Table Data Stream) 원격 프로시저 호출(RPC) 프로토콜 스트림이 잘못되었습니다.이 RPC 요청에 너무 많은 매개 변수가 제공되었습니다.최대 2100입니다.
쿼리를 다음으로 변경했습니다.
var dept_ids = string.Join(" ", depts.ToStringArray());
from f in CUSTOMERS
where dept_ids.IndexOf(Convert.ToString(f.DEPT_id)) != -1
select f.NAME
사용.IndexOf()
오류를 수정했지만 쿼리가 느려졌습니다.이것을 해결할 다른 방법이 있습니까?정말 감사합니다.
나의 해결책(Guids
필터링 기준으로 사용할 ID 목록입니다.):
List<MyTestEntity> result = new List<MyTestEntity>();
for(int i = 0; i < Math.Ceiling((double)Guids.Count / 2000); i++)
{
var nextGuids = Guids.Skip(i * 2000).Take(2000);
result.AddRange(db.Tests.Where(x => nextGuids.Contains(x.Id)));
}
this.DataContext = result;
쿼리를 sql에 작성하고 엔티티를 첨부하는 것이 어떻습니까?
Linq에서 일한 지 오래되었지만, 다음과 같습니다.
IQuery q = Session.CreateQuery(@"
select *
from customerTable f
where f.DEPT_id in (" + string.Join(",", depts.ToStringArray()) + ")");
q.AttachEntity(CUSTOMER);
물론 주사를 맞지 않도록 보호해야겠지만, 그렇게 어렵지는 않을 겁니다.
LINQKit 프로젝트에는 이 문제를 해결하기 위해 이러한 문을 일괄 처리하는 기술이 있기 때문에 따라 LINQKit 프로젝트를 확인할 수 있습니다.저는 Predicate Builder를 사용하여 로컬 컬렉션을 더 작은 덩어리로 나누는 것이 아이디어라고 생각하지만, 저는 이 문제를 처리하는 더 자연스러운 방법을 찾고 있었기 때문에 솔루션을 자세히 검토하지 않았습니다.
안타깝게도 이 동작을 수정하라는 제 제안에 대한 Microsoft의 답변을 보면 .NET Framework 4.0 또는 이후 서비스 팩에 대해 이 문제를 해결하도록 설정된 계획이 없습니다.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=475984
업데이트:
저는 이것이 LINQ to SQL에 대해 수정될 것인지 아니면 MSDN 포럼의 ADO.NET Entity Framework에 대해 수정될 것인지에 대한 논의를 시작했습니다.이러한 주제에 대한 자세한 내용과 XML 및 SQL UDF를 사용하여 해결한 임시 해결 방법은 다음 게시물을 참조하십시오.
저도 비슷한 문제가 있었고, 두 가지 방법으로 해결할 수 있었습니다.
- 교차법
- 신분증으로 가입.
목록에 없는 값을 가져오기 위해 Except 메서드 또는 Left Join을 사용했습니다.
갱신하다
EntityFramework 6.2는 다음 쿼리를 성공적으로 실행합니다.
var employeeIDs = Enumerable.Range(3, 5000);
var orders =
from order in Orders
where employeeIDs.Contains((int)order.EmployeeID)
select order;
당신의 게시물은 조금 전의 것이었지만, 아마도 누군가가 이것으로부터 이익을 얻을 것입니다.Entity Framework는 사용자가 다른 매개 변수 수를 보낼 때마다 캐시에 추가되는 많은 쿼리 캐싱을 수행합니다."포함" 호출을 사용하면 SQL에서 "WHERE x IN(@p1, @p2....@pn)"과 같은 절을 생성하고 EF 캐시를 블롯합니다.
최근에 저는 이것을 다루는 새로운 방법을 찾았고, 당신이 전체 데이터 테이블을 매개 변수로 만들 수 있다는 것을 발견했습니다.방법은 다음과 같습니다.
먼저 사용자 정의 테이블 유형을 만들어야 하므로 SQL Server에서 이를 실행합니다(사용자 정의 유형을 "TableId"라고 불렀습니다).
CREATE TYPE [dbo].[TableId] AS TABLE(
Id[int] PRIMARY KEY
)
그런 다음 C#에서 데이터 테이블을 생성하여 유형과 일치하는 구조화된 매개 변수로 로드할 수 있습니다.원하는 만큼 데이터 행을 추가할 수 있습니다.
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
이것은 검색할 임의의 ID 목록입니다.목록을 원하는 만큼 크게 만들 수 있습니다.
dt.Rows.Add(24262);
dt.Rows.Add(24267);
dt.Rows.Add(24264);
사용자 지정 테이블 유형과 데이터 테이블을 사용하여 SqlParameter를 만듭니다.
SqlParameter tableParameter = new SqlParameter("@id", SqlDbType.Structured);
tableParameter.TypeName = "dbo.TableId";
tableParameter.Value = dt;
그런 다음 기존 테이블을 조인하는 컨텍스트에서 테이블 매개 변수의 값으로 SQL을 호출할 수 있습니다.이렇게 하면 ID 목록과 일치하는 모든 레코드가 제공됩니다.
var items = context.Dailies.FromSqlRaw<Dailies>("SELECT * FROM dbo.Dailies d INNER JOIN @id id ON d.Daily_ID = id.id", tableParameter).AsNoTracking().ToList();
Linq에서 생성된 IN 문에 매개 변수로 전달하기 전에 항상 디프 목록을 더 작은 집합으로 분할할 수 있습니다.다음을 참조:
큰 IEnumberable을 항목 고정량의 작은 IEnumberable로 나눕니다.
언급URL : https://stackoverflow.com/questions/656167/hitting-the-2100-parameter-limit-sql-server-when-using-contains
'programing' 카테고리의 다른 글
동면.최대 절전 모드 버전을 4.2.0으로 업그레이드하면 INTEGER를 사용할 수 없습니다.CR1 (0) | 2023.07.12 |
---|---|
집계 addToSet 결과 정렬 중 (0) | 2023.07.12 |
페르시아 문자만 허용하는 정규식 (0) | 2023.07.12 |
SQL 쿼리 동등성 입증 (0) | 2023.07.12 |
Enter() 경로 가드 앞에서 사용할 때 필요한 소품이 누락됨 (0) | 2023.07.12 |