자습서: Azure Cosmos DB for NoSQL로 ASP.NET 웹 애플리케이션 개발
적용 대상: NoSQL
.NET용 Azure SDK를 사용하면 C#의 LINQ 또는 SQL 쿼리 문자열을 사용하여 API for NoSQL 컨테이너에서 데이터를 쿼리할 수 있습니다. 이 자습서에서는 자리 표시자 데이터를 사용하여 API에서 대신 쿼리하는 기존 ASP.NET 웹 애플리케이션을 업데이트하는 프로세스를 안내합니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- API for NoSQL을 사용하여 데이터베이스/컨테이너 만들기 및 채우기
- 템플릿에서 ASP.NET 웹 애플리케이션 만들기
- .NET용 Azure SDK를 사용하여 API for NoSQL 컨테이너의 데이터 쿼리
필수 조건
- 기존 Azure Cosmos DB API for NoSQL 계정.
- 기존 Azure 구독이 있는 경우 새 계정을 만듭니다.
- Azure 구독이 없으신가요? 신용 카드 없이 Azure Cosmos DB를 무료로 사용해 볼 수 있습니다.
- Visual Studio Code
- .NET 6(LTS) 이상
- C# 애플리케이션 작성 경험
NoSQL 리소스에 대한 API 만들기
먼저 기존 API for NoSQL 계정에 데이터베이스 및 컨테이너를 만듭니다. 그런 다음, cosmicworks
dotnet 도구를 사용하여 이 계정을 데이터로 채웁니다.
Azure Portal 기존 API for NoSQL 계정으로 이동합니다.
리소스 메뉴에서 키를 선택합니다.
키 페이지에서 PRIMARY CONNECTION STRING* 필드의 값을 확인하고 기록합니다. 이 값은 자습서 전체에서 사용됩니다.
리소스 메뉴에서 데이터 탐색기를 선택합니다.
Data Explorer 페이지의 명령 모음에서 새 컨테이너 옵션을 선택합니다.
새 컨테이너 대화 상자에서 다음 설정을 사용하여 새 컨테이너를 만듭니다.
설정 값 데이터베이스 ID cosmicworks
데이터베이스 처리량 유형 수동 데이터베이스 처리량 1000
컨테이너 ID products
파티션 키 /category/name
Important
이 자습서에서는 먼저 공유 처리량에서 최대 1,000RU/s까지 데이터베이스를 스케일링하여 데이터 마이그레이션에 대한 성능을 최대화합니다. 데이터 마이그레이션이 완료되면 프로비저닝된 처리량 400 RU/s로 스케일링 다운합니다.
확인을 선택하여 데이터베이스와 컨테이너를 만듭니다.
터미널을 열고 명령을 실행하여 컨테이너를 데이터로 채웁니다.
팁
여기서 Azure Cloud Shell을 사용할 수도 있습니다.
NuGet에서
cosmicworks
dotnet 도구의 v2를 설치합니다.dotnet tool install --global cosmicworks --version 2.*
cosmicworks
도구를 사용하여 이 랩의 앞부분에서 기록해 둔 URI 및 기본 키 값을 사용하여 샘플 제품 데이터로 API for NoSQL 계정을 채웁니다. 이러한 기록해 둔 값은 각각endpoint
및key
매개 변수에 사용됩니다.cosmicworks \ --number-of-products 1759 \ --number-of-employees 0 \ --disable-hierarchical-partition-keys \ --connection-string <nosql-connection-string>
명령줄 도구의 출력을 확인합니다. 컨테이너에 1759개의 항목을 추가해야 합니다. 포함된 예제 출력은 간단히 나타내기 위해 잘립니다.
── Parsing connection string ──────────────────────────────────────────────────────────────── ╭─Connection string──────────────────────────────────────────────────────────────────────────╮ │ AccountEndpoint=https://<account-name>.documents.azure.com:443/;AccountKey=<account-key>; │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ── Populating data ────────────────────────────────────────────────────────────────────────── ╭─Products configuration─────────────────────────────────────────────────────────────────────╮ │ Database cosmicworks │ │ Container products │ │ Count 1,759 │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ... [SEED] 00000000-0000-0000-0000-000000005951 | Road-650 Black, 60 - Bikes [SEED] 00000000-0000-0000-0000-000000005950 | Mountain-100 Silver, 42 - Bikes [SEED] 00000000-0000-0000-0000-000000005949 | Men's Bib-Shorts, L - Clothing [SEED] 00000000-0000-0000-0000-000000005948 | ML Mountain Front Wheel - Components [SEED] 00000000-0000-0000-0000-000000005947 | Mountain-500 Silver, 42 - Bikes
계정의 Data Explorer 페이지로 돌아갑니다.
데이터 섹션에서
cosmicworks
데이터베이스 노드를 확장한 다음, 스케일링을 선택합니다.처리량을 1,000에서 400으로 줄입니다.
명령 모음에서 저장을 선택합니다.
데이터 섹션에서 제품 컨테이너 노드를 확장하고 선택합니다.
명령 모음에서 새 SQL 쿼리를 선택합니다.
쿼리 편집기에서 이 SQL 쿼리 문자열을 추가합니다.
SELECT p.sku, p.price FROM products p WHERE p.price < 2000 ORDER BY p.price DESC
쿼리 실행을 선택하여 쿼리를 실행하고 결과를 관찰합니다.
결과는 최고가부터 최저가까지 정렬된 2,000보다 작은
price
값을 사용하여 컨테이너에 있는 모든 항목의 페이지 매긴 배열입니다. 간단히 하기 위해 여기에는 출력의 하위 집합이 포함됩니다.[ { "sku": "BK-R79Y-48", "price": 1700.99 }, ... { "sku": "FR-M94B-46", "price": 1349.6 }, ...
쿼리 편집기의 내용을 이 쿼리로 바꾼 다음, 쿼리 실행을 다시 선택하여 결과를 확인합니다.
SELECT p.name, p.category.name AS category, p.category.subCategory.name AS subcategory, p.tags FROM products p JOIN tag IN p.tags WHERE STRINGEQUALS(tag, "yellow", true)
결과는 name 값이
Tag-32
인 태그가 하나 이상 있는 항목만 포함하도록 필터링된 항목의 작은 배열입니다. 다시 말하지만, 간단히 하기 위해 여기에는 출력의 하위 집합이 포함됩니다.[ ... { "name": "HL Touring Frame - Yellow, 60", "category": "Components", "subcategory": "Touring Frames", "tags": [ "Components", "Touring Frames", "Yellow", "60" ] }, ... ]
ASP.NET 웹 애플리케이션 만들기
이제 샘플 프로젝트 템플릿을 사용하여 새 ASP.NET 웹 애플리케이션을 만듭니다. 그런 다음, 소스 코드를 탐색하고 샘플을 실행하여 .NET용 Azure SDK를 사용하여 Azure Cosmos DB 연결을 추가하기 전에 애플리케이션에 익숙해지도록 합니다.
Important
이 자습서에서는 NuGet에서 패키지를 투명하게 풀합니다. dotnet nuget list source
를 사용하여 패키지 원본을 확인할 수 있습니다. NuGet을 패키지 원본으로 사용하지 않는 경우 dotnet nuget add source
를 사용하여 사이트를 원본으로 설치합니다.
빈 디렉터리에서 터미널을 엽니다.
NuGet에서
cosmicworks.template.web
프로젝트 템플릿 패키지를 설치합니다.dotnet new install cosmicworks.template.web
새로 설치된
dotnet new cosmosdbnosql-webapp
템플릿을 사용하여 새 웹 애플리케이션 프로젝트를 만듭니다.dotnet new cosmosdbnosql-webapp
웹 애플리케이션 프로젝트를 빌드 및 실행합니다.
dotnet run
실행 명령의 출력을 확인합니다. 출력에는 애플리케이션이 실행 중인 포트 및 URL 목록이 포함됩니다.
... info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5000 info: Microsoft.Hosting.Lifetime[14] Now listening on: https://localhost:5001 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Production ...
새 브라우저를 열고 실행 중인 웹 애플리케이션으로 이동합니다. 실행 중인 애플리케이션의 세 페이지를 모두 확인합니다.
실행 중인 프로세스를 종료하여 실행 중인 애플리케이션을 중지합니다.
팁
Ctrl+C 명령을 사용하여 실행 중인 프로세스를 중지합니다. 또는 터미널을 닫았다가 다시 열 수 있습니다.
현재 프로젝트 폴더를 작업 영역으로 사용하여 Visual Studio Code 엽니다.
팁
터미널에서
code .
을(를) 실행하여 Visual Studio Code를 열고 자동으로 작업 디렉터리를 현재 작업 영역으로 열 수 있습니다.Services/ICosmosService.cs 파일로 이동한 후 엽니다.
RetrieveActiveProductsAsync
및RetrieveAllProductsAsync
기본 메서드 구현을 확인합니다. 이러한 메서드는 프로젝트를 처음 실행할 때 사용할 제품의 고정 목록을 만듭니다. 메서드 중 하나의 잘린 예제가 여기에 제공됩니다.public async Task<IEnumerable<Product>> RetrieveActiveProductsAsync() { await Task.Delay(1); return new List<Product>() { new Product(id: "baaa4d2d-5ebe-45fb-9a5c-d06876f408e0", category: new Category(name: "Components, Road Frames"), sku: "FR-R72R-60", name: """ML Road Frame - Red, 60""", description: """The product called "ML Road Frame - Red, 60".""", price: 594.83000000000004m), new Product(id: "bd43543e-024c-4cda-a852-e29202310214", category: new Category(name: "Components, Forks"), sku: "FK-5136", name: """ML Fork""", description: """The product called "ML Fork".""", price: 175.49000000000001m), ... }; }
Services/CosmosService.cs 파일로 이동한 후 엽니다. CosmosService 클래스의 현재 구현을 확인합니다. 이 클래스는 ICosmosService 인터페이스를 구현하지만 메서드를 재정의하지는 않습니다. 이 컨텍스트에서 클래스는 구현의 재정의가 인터페이스에 제공될 때까지 기본 인터페이스 구현을 사용합니다.
public class CosmosService : ICosmosService { }
마지막으로 Models/Product.cs 및 Models/Category.cs 파일을 찾아 엽니다. 각 파일에 정의된 레코드 종류를 확인합니다. 이러한 형식은 이 자습서 전체에서 쿼리에 사용됩니다.
public record Product( string id, Category category, string sku, string name, string description, decimal price );
public record Category( string name );
.NET SDK를 사용하여 데이터 쿼리
다음으로, 이 샘플 프로젝트에 .NET용 Azure SDK를 추가하고 라이브러리를 사용하여 API for NoSQL 컨테이너의 데이터를 쿼리합니다.
터미널로 돌아가서 NuGet에서
Microsoft.Azure.Cosmos
패키지를 추가 합니다.dotnet add package Microsoft.Azure.Cosmos
프로젝트를 빌드합니다.
dotnet build
다시 Visual Studio Code에서 Services/CosmosService.cs 파일로 이동합니다.
Microsoft.Azure.Cosmos
및Microsoft.Azure.Cosmos.Linq
네임스페이스에 대한 새 using 지시문을 추가합니다.using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq;
CosmosService 클래스 내에서
_client
라는CosmosClient
형식의 새private readonly
멤버를 추가합니다.private readonly CosmosClient _client;
CosmosService
클래스에 대한 빈 생성자를 새로 만듭니다.public CosmosService() { }
생성자 내에서 이전에 랩에서 기록해 둔
CosmosClient
기본 연결 문자열 값을 사용하여 문자열 매개 변수를 전달하는 클래스의 새 인스턴스를 만듭니다. 이 새 인스턴스를_client
멤버에 저장합니다.public CosmosService() { _client = new CosmosClient( connectionString: "<primary-connection-string>" ); }
CosmosService 클래스 내에서
container
라는Container
형식의 새private
속성을 만듭니다. get 접근자를 설정하여cosmicworks
데이터베이스와products
컨테이너를 반환합니다.private Container container { get => _client.GetDatabase("cosmicworks").GetContainer("products"); }
IEnumerable<Product>
를 반환하는RetrieveAllProductsAsync
라는 새 비동기 메서드를 만듭니다.public async Task<IEnumerable<Product>> RetrieveAllProductsAsync() { }
다음 단계에서는
RetrieveAllProductsAsync
메서드 내에 이 코드를 추가합니다.GetItemLinqQueryable<>
제네릭 메서드를 사용하여 LINQ(언어 통합 쿼리)를 생성하는 데 사용할 수 있는IQueryable<>
형식의 개체를 가져옵니다. 해당 개체를queryable
라는 변수에 저장합니다.var queryable = container.GetItemLinqQueryable<Product>();
Where
및OrderByDescending
확장 메서드를 사용하여 LINQ 쿼리를 생성합니다.ToFeedIterator
확장 메서드를 통해 반복기를 만들어 Azure Cosmos DB에서 데이터를 가져오고feed
라는 변수에 반복기를 저장합니다. 이 전체 식을 using 문으로 래핑하여 나중에 반복기를 삭제합니다.using FeedIterator<Product> feed = queryable .Where(p => p.price < 2000m) .OrderByDescending(p => p.price) .ToFeedIterator();
제네릭
List<>
형식을 사용하여results
라는 새 변수를 만듭니다.List<Product> results = new();
feed
변수의HasMoreResults
속성이 false를 반환할 때까지 반복되는 while 루프를 만듭니다. 이 루프는 서버 쪽 결과의 모든 페이지를 반복하도록 합니다.while (feed.HasMoreResults) { }
while 루프 내에서
feed
변수의ReadNextAsync
메서드를 비동기적으로 호출하고response
라는 변수에 결과를 저장합니다.while (feed.HasMoreResults) { var response = await feed.ReadNextAsync(); }
while 루프 내에서 foreach 루프를 사용하여 응답의 각 항목을 거친 후 살펴보고
results
목록에 추가합니다.while (feed.HasMoreResults) { var response = await feed.ReadNextAsync(); foreach (Product item in response) { results.Add(item); } }
results
목록을RetrieveAllProductsAsync
메서드의 출력으로 반환합니다.return results;
IEnumerable<Product>
를 반환하는RetrieveActiveProductsAsync
라는 새 비동기 메서드를 만듭니다.public async Task<IEnumerable<Product>> RetrieveActiveProductsAsync() { }
다음 단계에서는
RetrieveActiveProductsAsync
메서드 내에 이 코드를 추가합니다.SQL 쿼리에서
sql
이라는 새 문자열을 만들어 필터(@tagFilter
)가 각 항목의 tags 배열에 적용되는 여러 필드를 검색합니다.string sql = """ SELECT p.id, p.name, p.category, p.sku, p.description, p.price FROM products p JOIN tag IN p.tags WHERE STRINGEQUALS(tag, @tagFilter, true) """;
sql
문자열을 유일한 쿼리 매개 변수로 전달하는 이름이query
인 새QueryDefinition
변수를 만듭니다. 또한WithParameter
fluid 메서드를 사용하여red
값을@tagFilter
매개 변수에 적용합니다.var query = new QueryDefinition( query: sql ) .WithParameter("@tagFilter", "red");
GetItemQueryIterator<>
제네릭 메서드와query
변수를 사용하여 Azure Cosmos DB에서 데이터를 가져오는 반복기를 만듭니다.feed
변수에 반복자를 저장합니다. 이 전체 식을 using 문으로 래핑하여 나중에 반복기를 삭제합니다.using FeedIterator<Product> feed = container.GetItemQueryIterator<Product>( queryDefinition: query );
while 루프를 통해 결과의 여러 페이지를 반복하고 results라는 제네릭
List<>
에 값을 저장합니다. 결과를RetrieveActiveProductsAsync
메서드의 출력으로 반환합니다.List<Product> results = new(); while (feed.HasMoreResults) { FeedResponse<Product> response = await feed.ReadNextAsync(); foreach (Product item in response) { results.Add(item); } } return results;
Services/CosmosClient.cs 파일을 저장합니다.
팁
코드가 올바른지 확실하지 않은 경우 GitHub의 샘플 코드에 대해 소스 코드를 확인할 수 있습니다.
최종 애플리케이션 유효성 검사
마지막으로 핫 다시 로드를 사용하도록 설정하고 애플리케이션을 실행합니다. 애플리케이션을 실행하면 코드가 API for NoSQL에서 데이터에 액세스할 수 있는지 확인합니다.
터미널로 돌아가 애플리케이션을 실행합니다.
dotnet run
run 명령의 출력에는 애플리케이션이 실행 중인 포트 및 URL 목록이 포함됩니다. 새 브라우저를 열고 실행 중인 웹 애플리케이션으로 이동합니다. 실행 중인 애플리케이션의 세 페이지를 모두 확인합니다. 이제 각 페이지에 Azure Cosmos DB의 라이브 데이터가 포함됩니다.
리소스 정리
더 이상 필요하지 않은 경우 이 문서에서 사용된 데이터베이스를 삭제합니다. 이렇게 하려면 계정 페이지로 이동하고 Data Explorer를 선택하고, cosmicworks
데이터베이스를 선택한 다음, 삭제를 선택합니다.
다음 단계
Azure Cosmos DB를 사용하여 첫 번째 .NET 웹 애플리케이션을 만들었으므로 이제 SDK를 좀 더 자세히 살펴보면서 더 많은 데이터를 가져오고, 복잡한 쿼리를 수행하고, Azure Cosmos DB for NoSQL 리소스를 관리할 수 있습니다.