Veri API oluşturucusu'ndaki (DAB) GraphQL uç noktaları, verileri hassas bir şekilde sorgulamanıza ve değiştirmenize olanak tanır.
Her sorgu tam olarak hangi alanlara ihtiyacınız olduğunu bildirir ve sonuçları filtreleme, sıralama ve sayfalama için bağımsız değişkenleri destekler.
VARSAYıLAN olarak DAB, GraphQL uç noktasını şu konumda barındırmaktadır:
https://{base_url}/graphql
Yapılandırma aracılığıyla kullanıma sunulan varlıklar otomatik olarak GraphQL şemasına eklenir.
Örneğin, books ve authors varlıklarınız varsa, her ikisi de şemada kök alanlar olarak görünür.
Uyarı
Şemayı ve otomatik tamamlama alanlarını keşfetmek için herhangi bir modern GraphQL istemcisini veya IDE'yi (Apollo, Uykusuzluk veya Visual Studio Code GraphQL uzantısı gibi) kullanın.
Veri API'si oluşturucusunda desteklenen anahtar sözcükler
| Konsept |
GraphQL |
Amaç |
| Yansıtma |
items |
Hangi alanların döndürüleceğini seçin |
| Filtering |
filtre |
Koşula bağlı olarak satırları kısıtlama |
| Sıralama |
orderBy |
Sıralama düzenini tanımlama |
| Sayfa Boyutu |
birinci |
Sayfa başına öğeleri sınırlama |
| Devam |
sonra |
Son sayfadan devam et |
Temel yapı
Her GraphQL sorgusu bir varlığı temsil eden bir kök alanla başlar.
Tüm GraphQL istekleri, sorguyu içeren bir JSON gövdesi ile POST, /graphql uç noktasına gönderilir.
{
books {
items {
id
title
year
pages
}
}
}
Yanıt, seçim kümenizle aynı şekle sahip bir JSON nesnesidir.
Sayfalandırma ve hata ayrıntıları yalnızca uygun olduğunda görünür.
Uyarı
Varsayılan olarak DAB, aksiruntime.pagination.default-page-size () yapılandırılmadığı sürece sorgu başına en fazla 100 öğe döndürür.
POST https://localhost:5001/graphql
Content-Type: application/json
{
"query": "{ books { items { id title year pages } } }"
}
Başarı:
{
"data": {
"books": {
"items": [
{ "id": 1, "title": "Dune", "year": 1965, "pages": 412 },
{ "id": 2, "title": "Foundation", "year": 1951, "pages": 255 }
]
}
}
}
Sayfalandırma ile başarı:
{
"data": {
"books": {
"items": [
{ "id": 1, "title": "Dune", "year": 1965, "pages": 412 },
{ "id": 2, "title": "Foundation", "year": 1951, "pages": 255 }
],
"hasNextPage": true,
"endCursor": "eyJpZCI6Mn0="
}
}
}
Hata:
{
"errors": [
{
"message": "Could not find item with the given key.",
"locations": [{ "line": 1, "column": 3 }],
"path": ["book_by_pk"]
}
]
}
curl -X POST "https://localhost:5001/graphql" \
-H "Content-Type: application/json" \
-d '{"query": "{ books { items { id title year pages } } }"}'
Aşağıdaki model sınıfları DAB GraphQL yanıtlarının seri durumdan çıkarılmalarını sağlar:
using System.Text.Json.Serialization;
public class GraphQLRequest
{
[JsonPropertyName("query")]
public string Query { get; set; } = string.Empty;
[JsonPropertyName("variables")]
public object? Variables { get; set; }
}
public class GraphQLResponse<T>
{
[JsonPropertyName("data")]
public T? Data { get; set; }
[JsonPropertyName("errors")]
public List<GraphQLError>? Errors { get; set; }
[JsonIgnore]
public bool IsSuccess => Errors is null || Errors.Count == 0;
}
public class GraphQLError
{
[JsonPropertyName("message")]
public string Message { get; set; } = string.Empty;
[JsonPropertyName("path")]
public List<string>? Path { get; set; }
}
public class BooksResponse
{
[JsonPropertyName("books")]
public BooksResult? Books { get; set; }
}
public class BooksResult
{
[JsonPropertyName("items")]
public List<Book>? Items { get; set; }
[JsonPropertyName("hasNextPage")]
public bool HasNextPage { get; set; }
[JsonPropertyName("endCursor")]
public string? EndCursor { get; set; }
}
public class Book
{
[JsonPropertyName("id")]
public int Id { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; } = string.Empty;
[JsonPropertyName("year")]
public int? Year { get; set; }
[JsonPropertyName("pages")]
public int? Pages { get; set; }
}
API'yi çağırın ve yanıtı deserileştirin.
public async Task<List<Book>> GetBooksAsync()
{
var request = new GraphQLRequest
{
Query = "{ books { items { id title year pages } } }"
};
var response = await httpClient.PostAsJsonAsync("graphql", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GraphQLResponse<BooksResponse>>();
if (result?.Errors?.Count > 0)
{
throw new Exception(result.Errors[0].Message);
}
return result?.Data?.Books?.Items ?? [];
}
Aşağıdaki veri sınıfları DAB GraphQL yanıtlarını modelleyen:
from dataclasses import dataclass, field
import requests
@dataclass
class Book:
id: int
title: str
year: int | None = None
pages: int | None = None
@dataclass
class GraphQLError:
message: str
path: list[str] | None = None
@dataclass
class BooksResult:
items: list[Book] = field(default_factory=list)
has_next_page: bool = False
end_cursor: str | None = None
@dataclass
class GraphQLResponse:
data: dict | None = None
errors: list[GraphQLError] | None = None
@property
def is_success(self) -> bool:
return self.errors is None or len(self.errors) == 0
API'yi çağırın ve yanıtı ayrıştırın:
def get_books(base_url: str) -> list[Book]:
query = "{ books { items { id title year pages } } }"
response = requests.post(
f"{base_url}/graphql",
json={"query": query}
)
response.raise_for_status()
data = response.json()
if "errors" in data and data["errors"]:
raise Exception(data["errors"][0]["message"])
items = data.get("data", {}).get("books", {}).get("items", [])
return [Book(**item) for item in items]
Aşağıdaki işlev GraphQL API'sini çağırır:
async function getBooks(baseUrl) {
const query = "{ books { items { id title year pages } } }";
const response = await fetch(`${baseUrl}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query }),
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const result = await response.json();
if (result.errors?.length > 0) {
throw new Error(result.errors[0].message);
}
return result.data?.books?.items ?? [];
}
Örnek kullanım:
const books = await getBooks("https://localhost:5001");
console.log(`Fetched ${books.length} books from the API.`);
Sorgu türleri
Her varlık iki standart kök sorgu destekler:
| Query |
Açıklama |
entity_by_pk |
Birincil anahtarına göre bir kayıt döndürür |
entities |
Filtrelerle eşleşen kayıtların listesini döndürür |
Bir kayıt döndüren örnek:
{
book_by_pk(id: 1010) {
title
year
}
}
Birçok değer döndüren örnek:
{
books {
items {
id
title
}
}
}
Sonuçları filtreleme
Döndürülecek kayıtları kısıtlamak için filter bağımsız değişkenini kullanın.
{
books(filter: { title: { contains: "Foundation" } }) {
items { id title }
}
}
Bu sorgu, başlığı "Foundation" olan tüm kitapları döndürür.
Filtreler karşılaştırmaları mantıksal işleçlerle birleştirebilir:
{
authors(filter: {
or: [
{ first_name: { eq: "Isaac" } }
{ last_name: { eq: "Asimov" } }
]
}) {
items { first_name last_name }
}
}
Desteklenen işleçler olan , eq, neq, lt ve lte için isNull bakın.
Sonuçları sıralama
orderBy bağımsız değişkeni kayıtların nasıl sıralanacağını tanımlar.
{
books(orderBy: { year: DESC, title: ASC }) {
items { id title year }
}
}
Bu, önce azalan düzende year ile ve ardından title ile sıralanmış kitapları geri döndürür.
Daha fazla bilgi için orderBy bağımsız değişken başvurusuna bakın.
Sonuçları sınırlama
Argüman, first tek bir istekte kaç kaydın döndürüleceğini sınırlandırır.
{
books(first: 5) {
items { id title }
}
}
Bu, varsayılan olarak birincil anahtara göre sıralanmış ilk beş kitabı döndürür.
Yapılandırılan en büyük sayfa boyutunu istemek için de kullanabilirsiniz first: -1 .
İlk bağımsız değişken referansında daha fazla bilgi edinin.
Devam eden sonuçlar
Sonraki sayfayı getirmek için, önceki sorgudaki imleçle after bağımsız değişkenini kullanın.
{
books(first: 5, after: "eyJpZCI6NX0=") {
items { id title }
}
}
Belirteç, after önceki sayfanın sona erdiği yeri işaretler.
Daha fazla bilgi için aşağıdaki bağımsız değişken başvurusuna bakın.
Alan seçimi (projeksiyon)
GraphQL'de yanıtta tam olarak hangi alanların görüneceğini seçersiniz.
SELECT * gibi bir joker karakter yoktur. Yalnızca ihtiyacınız olanı isteyin.
{
books {
items { id title price }
}
}
Yanıttaki alanları yeniden adlandırmak için diğer adları da kullanabilirsiniz:
{
books {
items {
bookTitle: title
cost: price
}
}
}
Ayrıntılar için Bakınız, alan projeksiyonu referansı.
Verileri değiştirme
GraphQL mutasyonları, varlık izinlerine bağlı olarak kayıtları oluşturmanıza, güncelleştirmenize ve silmenize olanak sağlar.
| Mutasyon |
Eylem |
createEntity |
Yeni öğe oluşturma |
updateEntity |
Var olan bir öğeyi güncelleştirme |
deleteEntity |
Öğeyi kaldırma |
Uyarı
Sonek _by_pk yalnızca sorgular için geçerlidir (örneğin, book_by_pk). Mutasyon adları bu soneki içermez—updateBook_by_pk veya deleteBook_by_pk yerine updateBook ve deleteBook kullanın.
Önemli
GraphQL mutasyonları için etkin bir veritabanı bağlantı havuzu gerekir. Bağlantı dizeniz Pooling=False veya MultipleActiveResultSets=False olarak ayarlanmışsa, mutasyonlar Implicit distributed transactions have not been enabled hatasıyla başarısız olur.
Pooling=True ve MultipleActiveResultSets=True (SQL Server) veya veritabanı sağlayıcınızın eşdeğerini ayarlayın.
Tavsiye
GraphQL aracılığıyla kullanıma sunulan saklı yordamlar için DAB, varlık adına execute ön ekini ekler. Örneğin, GetBookById adlı saklı yordam varlığı, şemada executeGetBookById olur. Daha fazla bilgi için saklı yordamlar bölümüne bakın.
Yeni bir kayıt oluştur
Yeni bir create öğe eklemek için mutasyon kullanın.
POST https://localhost:5001/graphql
Content-Type: application/json
{
"query": "mutation { createBook(item: { id: 2000, title: \"Leviathan Wakes\", year: 2011, pages: 577 }) { id title year pages } }"
}
curl -X POST "https://localhost:5001/graphql" \
-H "Content-Type: application/json" \
-d '{"query": "mutation { createBook(item: { id: 2000, title: \"Leviathan Wakes\", year: 2011, pages: 577 }) { id title year pages } }"}'
var request = new GraphQLRequest
{
Query = @"
mutation CreateBook($item: CreateBookInput!) {
createBook(item: $item) { id title year pages }
}",
Variables = new
{
item = new { id = 2000, title = "Leviathan Wakes", year = 2011, pages = 577 }
}
};
var response = await httpClient.PostAsJsonAsync("graphql", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GraphQLResponse<CreateBookResponse>>();
if (result?.Errors?.Count > 0)
{
throw new Exception(result.Errors[0].Message);
}
query = """
mutation CreateBook($item: CreateBookInput!) {
createBook(item: $item) { id title year pages }
}
"""
variables = {
"item": {"id": 2000, "title": "Leviathan Wakes", "year": 2011, "pages": 577}
}
response = requests.post(
f"{base_url}/graphql",
json={"query": query, "variables": variables}
)
response.raise_for_status()
data = response.json()
if "errors" in data and data["errors"]:
raise Exception(data["errors"][0]["message"])
const query = `
mutation CreateBook($item: CreateBookInput!) {
createBook(item: $item) { id title year pages }
}
`;
const variables = {
item: { id: 2000, title: "Leviathan Wakes", year: 2011, pages: 577 },
};
const response = await fetch(`${baseUrl}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables }),
});
const result = await response.json();
if (result.errors?.length > 0) {
throw new Error(result.errors[0].message);
}
Var olan kaydı güncelleştir
Var olan bir update öğedeki belirli alanları değiştirmek için bir mutasyon kullanın.
POST https://localhost:5001/graphql
Content-Type: application/json
{
"query": "mutation { updateBook(id: 2000, item: { title: \"Leviathan Wakes\", year: 2011, pages: 577 }) { id title year pages } }"
}
curl -X POST "https://localhost:5001/graphql" \
-H "Content-Type: application/json" \
-d '{"query": "mutation { updateBook(id: 2000, item: { title: \"Leviathan Wakes\", year: 2011, pages: 577 }) { id title year pages } }"}'
var request = new GraphQLRequest
{
Query = @"
mutation UpdateBook($id: Int!, $item: UpdateBookInput!) {
updateBook(id: $id, item: $item) { id title year pages }
}",
Variables = new
{
id = 2000,
item = new { title = "Leviathan Wakes", year = 2011, pages = 577 }
}
};
var response = await httpClient.PostAsJsonAsync("graphql", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GraphQLResponse<UpdateBookResponse>>();
if (result?.Errors?.Count > 0)
{
throw new Exception(result.Errors[0].Message);
}
query = """
mutation UpdateBook($id: Int!, $item: UpdateBookInput!) {
updateBook(id: $id, item: $item) { id title year pages }
}
"""
variables = {
"id": 2000,
"item": {"title": "Leviathan Wakes", "year": 2011, "pages": 577}
}
response = requests.post(
f"{base_url}/graphql",
json={"query": query, "variables": variables}
)
response.raise_for_status()
data = response.json()
if "errors" in data and data["errors"]:
raise Exception(data["errors"][0]["message"])
const query = `
mutation UpdateBook($id: Int!, $item: UpdateBookInput!) {
updateBook(id: $id, item: $item) { id title year pages }
}
`;
const variables = {
id: 2000,
item: { title: "Leviathan Wakes", year: 2011, pages: 577 },
};
const response = await fetch(`${baseUrl}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables }),
});
const result = await response.json();
if (result.errors?.length > 0) {
throw new Error(result.errors[0].message);
}
Kayıt silme
delete Bir öğeyi birincil anahtara göre kaldırmak için mutasyon kullanın.
POST https://localhost:5001/graphql
Content-Type: application/json
{
"query": "mutation { deleteBook(id: 2000) { id title } }"
}
curl -X POST "https://localhost:5001/graphql" \
-H "Content-Type: application/json" \
-d '{"query": "mutation { deleteBook(id: 2000) { id title } }"}'
var request = new GraphQLRequest
{
Query = @"
mutation DeleteBook($id: Int!) {
deleteBook(id: $id) { id title }
}",
Variables = new { id = 2000 }
};
var response = await httpClient.PostAsJsonAsync("graphql", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GraphQLResponse<DeleteBookResponse>>();
if (result?.Errors?.Count > 0)
{
throw new Exception(result.Errors[0].Message);
}
query = """
mutation DeleteBook($id: Int!) {
deleteBook(id: $id) { id title }
}
"""
variables = {"id": 2000}
response = requests.post(
f"{base_url}/graphql",
json={"query": query, "variables": variables}
)
response.raise_for_status()
data = response.json()
if "errors" in data and data["errors"]:
raise Exception(data["errors"][0]["message"])
const query = `
mutation DeleteBook($id: Int!) {
deleteBook(id: $id) { id title }
}
`;
const variables = { id: 2000 };
const response = await fetch(`${baseUrl}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables }),
});
const result = await response.json();
if (result.errors?.length > 0) {
throw new Error(result.errors[0].message);
}