C# LINQ.DocumentDb CreateDocument에서 작업하지 않는 모든 항목쿼리
특정 유형의 제품이 있는 아트에 문의하려고 합니다.제 미술 모델은 다음과 같습니다.
public string Title { get; set; }
public string Description { get; set; }
public List<Product> Products { get; set; }
public string PaintedLocation { get; set; }
여기서 제가 하고 있는 것은 다음 LINQ 쿼리뿐입니다.
List<Art> items = DocumentDbHelper.Client.CreateDocumentQuery<Art>(collection.DocumentsLink)
.Where(i => i.type == "art")
.Where(i => i.Products.Any(p => p.Name == productType))
.AsEnumerable()
.ToList();
다음 오류가 발생합니다.
"Method 'Any' is not supported."
코드가 지원되는 항목을 확인하기 위해 참조하는 페이지로 이동했지만 Any()가 지원되지 않는다고 표시되지 않아 잘못된 작업을 수행하고 있는 것 같습니다.어떤 도움이든 감사합니다.
갱신하다
이것은 저에게 정말 이상한 일입니다. 그래서 저는 이 문제를 더 잘 디버그하기 위해 두 결과에서 무엇이 반환되는지 보기 위해 이 문제를 분리했습니다.
List<Art> items = DocumentDbHelper.Client.CreateDocumentQuery<Art>(collection.DocumentsLink)
.Where(i => i.Id.Contains("art"))
.AsEnumerable()
.ToList();
items = items.Where(i => i.Products.Any(p => p.Name == productType))
.AsEnumerable()
.ToList();
어떤 이유에서인지, 저는 이것을 좋아하지 않습니다. 왜냐하면 제가 목록으로 변환하기 때문에 쿼리를 두 번 실행하기 때문입니다. 하지만 적어도 Any()와 Select()가 기술적으로 작동해야 한다는 증거입니다.
다음에 대한 LINQ 쿼리의 가장 큰 혼란 중 하나입니다.IQueryable<T>
그들이 정확히 같은 것처럼 보인다는 것입니다.IEnumerable<T>
음, 전자는 사용하고 있습니다.Expression<Func<..>>
후자가 사용될 때마다Func<..>
그러나 명시적 선언을 사용하는 경우를 제외하고는 이는 그다지 눈에 띄지 않으며 중요하지 않아 보입니다.하지만, 큰 차이는 런타임에 나타납니다.
원스 더IEnumerable<T>
쿼리가 성공적으로 컴파일되었습니다. 런타임에 작동합니다. 이 경우는 그렇지 않습니다.IQueryable<T>
.aIQueryable<T>
쿼리는 실제로 쿼리 공급자가 런타임에 처리하는 식 트리입니다.
쿼리 제공자가 쿼리 컴파일 시간에 관여하지 않기 때문에 한쪽에서, 다른 쪽에서 이것은 큰 이점입니다. (모든 메서드는 다음과 같이 확장 메서드로 제공됩니다.)Queryable
클래스), 공급자가 일부 구성/구성 요소를 지원하는지 여부를 런타임까지 알 수 없습니다.Link to Entities를 사용하는 사람들은 그것을 잘 알고 있습니다.문제를 더 어렵게 만드는 것은 특정 쿼리 공급자가 지원하는 것과 더 중요하게는 지원하지 않는 것에 대한 명확한 문서가 없습니다(제공한 "지원되는 항목" 링크에서 알 수 있듯이).
해결책은 무엇입니까?(및 두 번째 코드가 작동하는 이유)
이 방법은 가능한 최대 쿼리 부분(즉, 쿼리 공급자가 지원하는)을 작성하는 것입니다.IQueryable<T>
다음으로 전환합니다.IEnumerable<T>
나머지 작업을 수행합니다(기본적으로, 일단 컴파일되면,IEnumerable<T>
쿼리가 작동합니다).는 스치는다같수다니행됩이과에 의해 됩니다.AsEnumerable()
call. 두 되지 않는 unsupported 코작동가다합니드그번두째래서▁un▁is▁call▁because다▁code▁-니동합작▁second▁workingsupported▁and▁your▁that. 지원되지 않기 때문입니다.Any
메서드가 DocumentDb 쿼리 공급자 컨텍스트에 더 이상 없습니다.:ToList
호출할 필요가 없으며 쿼리가 두 번 실행되지 않습니다. 실제로 이 방법으로는 단일 쿼리가 없고 데이터베이스와 메모리에 하나씩 있는 두 개의 쿼리가 있습니다.
따라서 다음과 같은 것으로 충분합니다.
List<Art> items = DocumentDbHelper.Client.CreateDocumentQuery<Art>(collection.DocumentsLink)
.Where(i => i.type == "art")
.AsEnumerable() // The context switch!
.Where(i => i.Products.Any(p => p.Name == productType))
.ToList();
마지막으로 DocumentDb 쿼리 공급자가 실제로 지원하는 것은 무엇입니까?
설명서에서는 명확하지 않지만, 정답은 다음과 같습니다. 정확히 (그리고 유일하게) 거기에 포함된 내용입니다. 연산자 더 잘 말하면 즉게지또입쿼는연리원산되자니다표나현더은유일하는또입▁(▁operators▁say▁in▁the,니다▁supportedor즉▁query연▁only()입니다.Queryable
또는Enumerable
메서드는 "확장 메서드"입니다.
- 선택한다.
- 다수 선택
- 어디에
- 주문 기준
- 내림차순 정렬
보시다시피 매우 제한적입니다. 연산자는 , 조인및는잊십시오리어버자.Any
,Contains
,Count
,First
,Last
단입니다 :)등 단 한가지 좋은 점은 쉽게 외울 수 있다는 것입니다 :)
내가 그걸 어떻게 알아?문서에서 명확하지 않은 것이 있을 때는 보통 시행착오나 디컴파일러를 사용합니다.이 경우 전자는 해당되지 않으므로 후자를 사용했습니다. 클래스의 .DocumentQueryEvaluator
에의 에.Microsoft.Azure.Documents.Client.dll
.
최신 Azure 문서를 사용하고 있습니다.DB nug 대상입니다.넷 4.6.
<package id="Microsoft.Azure.DocumentDB" version="1.5.0" targetFramework="net46" />
여기 제게 잘 작동하는 샘플 코드가 있습니다.
using System.Collections.Generic;
using System.Linq;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
var book = client.CreateDocumentQuery<Book>(collectionLink)
.Where(b => b.Title == "War and Peace")
.Where(b => b.Publishers.Any(p => p.IsNormalized()))
.AsEnumerable().FirstOrDefault();
public class Book
{
[JsonProperty("title")]
public string Title { get; set; }
public Author Author { get; set; }
public int Price { get; set; }
public List<string> Publishers { get; set; }
}
public class Author
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
은 보오시십해를 해 봐야 .IEnumerable.Contains
를 하세요.
DbHelper.Client.CreateDocumentQuery<Art>(collection.DocumentsLink)
.Where(i => i.type == "art")
.Where(i => i.Products
.Select(p => p.Name).Contains(productType))
.AsEnumerable()
.ToList();
문서 DB는 컬렉션의 색인을 사용할 수 있으므로 현재 가장 성능이 뛰어난 솔루션은 SQL 구문을 사용하는 것입니다.
예:
SELECT a
FROM a
JOIN p in a.Products
WHERE ARRAY_CONTAINS(a.Id, 'art')
AND p.Name = 'My Product Type'
단점은 고유하지 않은 결과를 얻을 수 있으며 결과를 클라이언트 측에서 구분해야 한다는 것입니다.
이 문제를 DocumentDB에 포함시키려면 다음 항목에 투표하는 것이 도움이 될 것입니다. https://feedback.azure.com/forums/263030-documentdb/suggestions/14829654-support-sub-query-functions-like-exists-not-exist
이것을 시도해 보는 게 어때요?
List<Art> items = DocumentDbHelper.Client.CreateDocument(collection.DocumentsLink)
.Where(i => i.type == "art" && i.Products.Any(p => p.Name == productType))
.AsEnumerable()
.ToList();
언급URL : https://stackoverflow.com/questions/33839854/c-sharp-linq-any-not-working-on-documentdb-createdocumentquery
'programing' 카테고리의 다른 글
.net 콘솔 응용 프로그램에 메시지 상자 표시 (0) | 2023.05.22 |
---|---|
IIS7 배포 - '시스템'을 복제합니다.web.extensions/scriptResourceHandler' 섹션 (0) | 2023.05.22 |
Eclipse 패키지 탐색기에서 계층형 패키지 구조를 보는 방법 (0) | 2023.05.17 |
재시도 로직을 작성하는 가장 깨끗한 방법은 무엇입니까? (0) | 2023.05.17 |
Angular 4 토큰 새로 고침 후 가로채기 재시도 요청 (0) | 2023.05.17 |