diff --git a/material-sistemas-distribuidos/src/css/code.css b/material-sistemas-distribuidos/src/css/code.css index e359930..a34f060 100644 --- a/material-sistemas-distribuidos/src/css/code.css +++ b/material-sistemas-distribuidos/src/css/code.css @@ -14,14 +14,16 @@ code { } code:not(pre *) { + font-size: .8em; background-color: var(--color-code-bg); color: var(--color-code-fg); - padding: 3px 6px; + padding: 2px 5px; border: 1px solid var(--color-code-border); border-radius: 6px; } pre:has(code) { + font-size: .9em; background-color: var(--color-codeblock-bg); color: var(--color-codeblock-fg); padding: 16px; diff --git a/material-sistemas-distribuidos/src/css/typography.css b/material-sistemas-distribuidos/src/css/typography.css index 2c962a3..beda715 100644 --- a/material-sistemas-distribuidos/src/css/typography.css +++ b/material-sistemas-distribuidos/src/css/typography.css @@ -20,7 +20,6 @@ h2 { code { font-family: var(--font-mono); - font-size: 16px; } em { diff --git a/material-sistemas-distribuidos/src/routes/bd/+page.svelte b/material-sistemas-distribuidos/src/routes/bd/+page.svelte index 1364d88..1824fb9 100644 --- a/material-sistemas-distribuidos/src/routes/bd/+page.svelte +++ b/material-sistemas-distribuidos/src/routes/bd/+page.svelte @@ -58,7 +58,8 @@ dotnet add package MySqlConnector`} O banco de dados que vamos utilizar possui uma tabela com o nome Livro. Esta tabela possui os seguintes campos:

-
{`Isbn         VARCHAR(255) PRIMARY KEY NOT NULL,
+
{`Id           BIGINT       PRIMARY KEY NOT NULL AUTO_INCREMENT,
+Isbn         VARCHAR(255) NOT NULL,
 Titulo       VARCHAR(512) NOT NULL,
 Autor        TEXT         NOT NULL,
 Genero       TEXT         NOT NULL,
@@ -98,19 +99,19 @@ app.MapPost("/livros", () =>
 });
 
 // Edita um livro.
-app.MapPut("/livros/{isbn}", () =>
+app.MapPut("/livros/{id}", () =>
 {
     
 });
 
 // Obtém os dados de um livro individual.
-app.MapGet("/livros/{isbn}", () =>
+app.MapGet("/livros/{id}", () =>
 {
     
 });
 
 // Remove um livro.
-app.MapDelete("/livros/{isbn}", () =>
+app.MapDelete("/livros/{id}", () =>
 {
     
 });
@@ -126,6 +127,7 @@ app.Run();`}
public class Livro { + public long Id { get; set; } public string? Isbn { get; set; } public string? Titulo { get; set; } public string? Autor { get; set; } @@ -184,7 +186,7 @@ public class LivroRepository

- O valor de retorno será um IEnumerable<Livro>. Um IEnumerable é uma interface do dotnet que representa + O valor de retorno será um IEnumerable<Livro>. Um IEnumerable é uma interface que representa qualquer sequência iterável de objetos. Por exemplo, um objeto List<T> ou um vetor T[] são iteráveis, portanto podem ser retornados neste método.

@@ -215,7 +217,7 @@ public class LivroRepository var offset = take * Math.Max(pagina-1, 0); var lista = new List(); - cmd.CommandText = "SELECT Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro ORDER BY CriadoEm LIMIT @offset,@take"; + cmd.CommandText = "SELECT Id, Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro ORDER BY CriadoEm LIMIT @offset,@take"; cmd.Parameters.AddWithValue("offset", offset); cmd.Parameters.AddWithValue("take", take); @@ -225,16 +227,17 @@ public class LivroRepository { lista.Add(new() { - Isbn = reader.GetString(0), - Titulo = reader.GetString(1), - Autor = reader.GetString(2), - Genero = reader.GetString(3), - Descricao = reader.GetString(4), - Foto = reader.GetString(5), - Keywords = reader.GetString(6), - Ativo = reader.GetBoolean(7), - CriadoEm = reader.GetDateTime(8), - AtualizadoEm = reader.GetDateTime(9), + Id = reader.GetInt64(0), + Isbn = reader.GetString(1), + Titulo = reader.GetString(2), + Autor = reader.GetString(3), + Genero = reader.GetString(4), + Descricao = reader.GetString(5), + Foto = reader.GetString(6), + Keywords = reader.GetString(7), + Ativo = reader.GetBoolean(8), + CriadoEm = reader.GetDateTime(9), + AtualizadoEm = reader.GetDateTime(10), }); } @@ -268,7 +271,7 @@ await conn.OpenAsync();`}

O modelo de programação assíncrona é uma característica que - é praticamente ubíqua no dotnet, mas não precisamos nos aprofundar nela por enquanto. Basta saber que devemos utilizar await em métodos assíncronos, e + está presente em quase toda a linguagem, mas não precisamos nos aprofundar nela por enquanto. Basta saber que devemos utilizar await em métodos assíncronos, e que se o utilizarmos, o nosso método deve ser também assíncrono, sendo declarado com async Task.

@@ -292,7 +295,7 @@ var lista = new List();`} A variável lista é uma lista de objetos Livro que irá guardar todos os resultados da consulta, e depois será retornada.

-
{`cmd.CommandText = "SELECT Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro ORDER BY CriadoEm LIMIT @offset,@take";
+
{`cmd.CommandText = "SELECT Id, Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro ORDER BY CriadoEm LIMIT @offset,@take";
 cmd.Parameters.AddWithValue("offset", offset);
 cmd.Parameters.AddWithValue("take", take);`}
@@ -312,24 +315,26 @@ cmd.Parameters.AddWithValue("take", take);`}
{ lista.Add(new() { - Isbn = reader.GetString(0), - Titulo = reader.GetString(1), - Autor = reader.GetString(2), - Genero = reader.GetString(3), - Descricao = reader.GetString(4), - Foto = reader.GetString(5), - Keywords = reader.GetString(6), - Ativo = reader.GetBoolean(7), - CriadoEm = reader.GetDateTime(8), - AtualizadoEm = reader.GetDateTime(9), + Id = reader.GetInt64(0), + Isbn = reader.GetString(1), + Titulo = reader.GetString(2), + Autor = reader.GetString(3), + Genero = reader.GetString(4), + Descricao = reader.GetString(5), + Foto = reader.GetString(6), + Keywords = reader.GetString(7), + Ativo = reader.GetBoolean(8), + CriadoEm = reader.GetDateTime(9), + AtualizadoEm = reader.GetDateTime(10), }); }`}

Este laço é repetido enquanto await reader.ReadAsync() retornar true, o que significa que existe um resultado da consulta que pode ser lido. Quando isso acontece, podemos ler as colunas do resultado através dos métodos de reader, como reader.GetString(0). O número passado como - parâmetro para estas funções indica a posição da coluna lida. Por exemplo, na consulta que realizamos (SELECT Isbn, Titulo, ...), a coluna Isbn é a primeira, - portanto, para ler este valor, devemos executar reader.GetString(0). Titulo é a segunda, então o seu valor é obtido através de reader.GetString(1), e assim + parâmetro para estas funções indica a posição da coluna lida. Por exemplo, na consulta que realizamos (SELECT Id, Isbn, Titulo, ...), a coluna Id é a primeira, + portanto, para ler este valor, devemos executar reader.GetInt64(0) (Int64, um número inteiro de 64-bits, é um sinônimo para long). + Isbn é a segunda, então o seu valor é obtido através de reader.GetString(1), e assim sucessivamente.

@@ -362,21 +367,21 @@ app.MapGet("/livros", async () => Agora execute este endpoint. Se tudo deu certo, você verá alguns livros cadastrados no retorno.

-

Obtendo um livro pelo ISBN

+

Obtendo um livro pela chave primária

- O ISBN é a chave primária da tabela. Vamos implementar um método que consulta um único livro a partir deste dado. + O Id é a chave primária da tabela. Vamos implementar um método que consulta um único livro a partir deste dado.

-
{`public async Task Obter(string isbn)
+
{`public async Task Obter(long id)
 {
     using var conn = new MySqlConnection(ConnString);
     using var cmd  = conn.CreateCommand();
 
     await conn.OpenAsync();
 
-    cmd.CommandText = "SELECT Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro WHERE Isbn=@isbn";
-    cmd.Parameters.AddWithValue("isbn", isbn);
+    cmd.CommandText = "SELECT Id, Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro WHERE Id=@id";
+    cmd.Parameters.AddWithValue("id", id);
 
     using var reader = await cmd.ExecuteReaderAsync();
 
@@ -384,21 +389,22 @@ app.MapGet("/livros", async () =>
 
     if (!existe)
     {
-        throw new Exception($"Livro com ISBN {isbn} não encontrado");
+        throw new Exception($"Livro {id} não encontrado");
     }
 
     return new()
     {
-        Isbn         = reader.GetString(0),
-        Titulo       = reader.GetString(1),
-        Autor        = reader.GetString(2),
-        Genero       = reader.GetString(3),
-        Descricao    = reader.GetString(4),
-        Foto         = reader.GetString(5),
-        Keywords     = reader.GetString(6),
-        Ativo        = reader.GetBoolean(7),
-        CriadoEm     = reader.GetDateTime(8),
-        AtualizadoEm = reader.GetDateTime(9),
+        Id           = reader.GetInt64(0),
+        Isbn         = reader.GetString(1),
+        Titulo       = reader.GetString(2),
+        Autor        = reader.GetString(3),
+        Genero       = reader.GetString(4),
+        Descricao    = reader.GetString(5),
+        Foto         = reader.GetString(6),
+        Keywords     = reader.GetString(7),
+        Ativo        = reader.GetBoolean(8),
+        CriadoEm     = reader.GetDateTime(9),
+        AtualizadoEm = reader.GetDateTime(10),
     };
 }`}
@@ -406,11 +412,11 @@ app.MapGet("/livros", async () => As três primeiras linhas deste método, assim como no de listagem, abre uma conexão com o banco de dados.

-
{`cmd.CommandText = "SELECT Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro WHERE Isbn=@isbn";
-cmd.Parameters.AddWithValue("isbn", isbn);`}
+
{`cmd.CommandText = "SELECT Id, Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro WHERE Id=@id";
+cmd.Parameters.AddWithValue("id", id);`}

- A consulta é montada na variável cmd, o parâmetro isbn é adicionado ao comando. + A consulta é montada na variável cmd, o parâmetro id é adicionado ao comando.

{`using var reader = await cmd.ExecuteReaderAsync();
@@ -419,27 +425,28 @@ var existe = await reader.ReadAsync();
 
 if (!existe)
 {
-    throw new Exception($"Livro com ISBN {isbn} não encontrado");
+    throw new Exception($"Livro {id} não encontrado");
 }
 
 return new()
 {
-    Isbn         = reader.GetString(0),
-    Titulo       = reader.GetString(1),
-    Autor        = reader.GetString(2),
-    Genero       = reader.GetString(3),
-    Descricao    = reader.GetString(4),
-    Foto         = reader.GetString(5),
-    Keywords     = reader.GetString(6),
-    Ativo        = reader.GetBoolean(7),
-    CriadoEm     = reader.GetDateTime(8),
-    AtualizadoEm = reader.GetDateTime(9),
+    Id           = reader.GetInt64(0),
+    Isbn         = reader.GetString(1),
+    Titulo       = reader.GetString(2),
+    Autor        = reader.GetString(3),
+    Genero       = reader.GetString(4),
+    Descricao    = reader.GetString(5),
+    Foto         = reader.GetString(6),
+    Keywords     = reader.GetString(7),
+    Ativo        = reader.GetBoolean(8),
+    CriadoEm     = reader.GetDateTime(9),
+    AtualizadoEm = reader.GetDateTime(10),
 };`}

Assim como na listagem, await cmd.ExecuteReaderAsync() é chamado para ler os resultados da consulta. - Como esperamos que só haja um registro com aquele ISBN, executamos await reader.ReadAsync() apenas uma vez. - Se este método retorna false, é por que nenhum registro foi encontrado com aquele ISBN. Neste caso, lançamos um erro. + Como esperamos que só haja um registro com aquele Id, executamos await reader.ReadAsync() apenas uma vez. + Se este método retorna false, é por que nenhum registro foi encontrado com esta chave primária. Neste caso, lançamos um erro. Do contrário, utilizamos os métodos de leitura do registro lido para montar um objeto Livro que será retornado.

@@ -448,10 +455,10 @@ return new()

{`// Obtém os dados de um livro individual.
-app.MapGet("/livros/{isbn}", async (string isbn) =>
+app.MapGet("/livros/{id}", async (long id) =>
 {
     var repo = new LivroRepository();
-    var res  = await repo.Obter(isbn);
+    var res  = await repo.Obter(id);
 
     return res;
 });`}
@@ -492,11 +499,6 @@ app.MapGet("/livros/{isbn}", async (string isbn) => AtualizadoEm = default, }; - if (livro.Isbn == "") - { - throw new Exception("O ISBN do livro é obrigatório."); - } - if (livro.Titulo == "") { throw new Exception("O título do livro é obrigatório."); @@ -570,12 +572,7 @@ app.MapGet("/livros/{isbn}", async (string isbn) => Fazemos isso nos campos do objeto livro para garantir que nenhum deles seja nulo, já que no banco de dados, todos os campos da tabela são NOT NULL.

-
{`if (livro.Isbn == "")
-{
-    throw new Exception("O ISBN do livro é obrigatório.");
-}
-
-if (livro.Titulo == "")
+
{`if (livro.Titulo == "")
 {
     throw new Exception("O título do livro é obrigatório.");
 }`}
@@ -635,14 +632,14 @@ app.MapPost("/livros", async (Livro livro) => O método de edição é similar ao de criação.

-
{`public async Task Editar(string isbn, Livro dados)
+
{`public async Task Editar(long id, Livro dados)
 {
     using var conn = new MySqlConnection(ConnString);
     using var cmd  = conn.CreateCommand();
 
     await conn.OpenAsync();
 
-    var livro = await Obter(isbn);
+    var livro = await Obter(id);
 
     livro.Titulo       = dados.Titulo?.Trim() ?? "";
     livro.Autor        = dados.Autor?.Trim() ?? "";
@@ -656,10 +653,10 @@ app.MapPost("/livros", async (Livro livro) =>
         @"
         UPDATE Livro SET
         Titulo=@titulo, Autor=@autor, Genero=@genero, Descricao=@descricao, Foto=@foto, Keywords=@keywords, AtualizadoEm=@atualizadoem
-        WHERE Isbn=@isbn
+        WHERE Id=@id
         ";
 
-    cmd.Parameters.AddWithValue("isbn",         isbn);
+    cmd.Parameters.AddWithValue("id",           id);
     cmd.Parameters.AddWithValue("titulo",       livro.Titulo);
     cmd.Parameters.AddWithValue("autor",        livro.Autor);
     cmd.Parameters.AddWithValue("genero",       livro.Genero);
@@ -677,7 +674,7 @@ app.MapPost("/livros", async (Livro livro) =>
     O método recebe dois parâmetros, um isbn que identifica o livro que será editado, e um objeto com os novos dados do livro.
   

-
{`var livro = await Obter(isbn);
+
{`var livro = await Obter(id);
 
 livro.Titulo       = dados.Titulo?.Trim() ?? "";
 livro.Autor        = dados.Autor?.Trim() ?? "";
@@ -688,7 +685,7 @@ livro.Keywords     = dados.Keywords?.Trim() ?? "";
 livro.AtualizadoEm = DateTime.Now;`}

- Chamamos a função Obter(string) que criamos para obter do banco de dados o livro que será editado. Em seguida, atribuímos a este objeto + Chamamos a função Obter(long) que criamos para obter do banco de dados o livro que será editado. Em seguida, atribuímos a este objeto os valores do objeto dados, formatando-os devidamente.

@@ -696,10 +693,10 @@ livro.AtualizadoEm = DateTime.Now;`}
@" UPDATE Livro SET Titulo=@titulo, Autor=@autor, Genero=@genero, Descricao=@descricao, Foto=@foto, Keywords=@keywords, AtualizadoEm=@atualizadoem - WHERE Isbn=@isbn + WHERE Id=@id "; -cmd.Parameters.AddWithValue("isbn", isbn); +cmd.Parameters.AddWithValue("id", id); cmd.Parameters.AddWithValue("titulo", livro.Titulo); cmd.Parameters.AddWithValue("autor", livro.Autor); cmd.Parameters.AddWithValue("genero", livro.Genero); @@ -721,10 +718,10 @@ return livro;`}

{`// Edita um livro.
-app.MapPut("/livros/{isbn}", async (string isbn, Livro livro) =>
+app.MapPut("/livros/{id}", async (long id, Livro livro) =>
 {
     var repo = new LivroRepository();
-    var res  = await repo.Editar(isbn, livro);
+    var res  = await repo.Editar(id, livro);
 
     return res;
 });`}
@@ -737,15 +734,15 @@ app.MapPut("/livros/{isbn}", async (string isbn, Livro livro) => Portanto, o método de remover será basicamente uma edição.

-
{`public async Task Desativar(string isbn)
+
{`public async Task Desativar(long id)
 {
     using var conn = new MySqlConnection(ConnString);
     using var cmd  = conn.CreateCommand();
 
     await conn.OpenAsync();
 
-    cmd.CommandText = "UPDATE Livro SET Ativo=false WHERE Isbn=@isbn";
-    cmd.Parameters.AddWithValue("isbn", isbn);
+    cmd.CommandText = "UPDATE Livro SET Ativo=false WHERE Id=@id";
+    cmd.Parameters.AddWithValue("id", id);
 
     await cmd.ExecuteNonQueryAsync();
 }`}
@@ -755,11 +752,11 @@ app.MapPut("/livros/{isbn}", async (string isbn, Livro livro) =>

{`// Remove um livro.
-app.MapDelete("/livros/{isbn}", async (string isbn) =>
+app.MapDelete("/livros/{id}", async (long id) =>
 {
     var repo = new LivroRepository();
 
-    await repo.Desativar(isbn);
+    await repo.Desativar(id);
 });`}

Finalizando

diff --git a/material-sistemas-distribuidos/src/routes/endpoints_2/+page.svelte b/material-sistemas-distribuidos/src/routes/endpoints_2/+page.svelte index bc3415b..b3b23f6 100644 --- a/material-sistemas-distribuidos/src/routes/endpoints_2/+page.svelte +++ b/material-sistemas-distribuidos/src/routes/endpoints_2/+page.svelte @@ -114,7 +114,7 @@ Donald Knuth - The Art of Computer Programming`}

- E se desejássemos obter um único livro, identificado pelo seu ISBN. Poderíamos fazer um endpoint: + E se desejássemos obter um único livro, identificado pela sua chave primária. Poderíamos fazer um endpoint:

{`Request:
@@ -125,7 +125,7 @@ Response:
 Yasunari Kawabata - Contos da Palma da Mão`}

- Note que agora a URI ficou /livros/9788574481371 onde 9788574481371 é o ISBN do livro, é um dado que o identifica e pode ser uma chave primária. + Note que agora a URI ficou /livros/9788574481371 onde 9788574481371 é a chave primária do livro, o dado que o identifica.

@@ -140,7 +140,7 @@ Response: 200 OK - 9788574481371 + 9788574481371 Contos da Palma da Mão Yasunari Kawabata `}

@@ -155,7 +155,7 @@ GET /livros/9788574481371 Response: 200 Ok { - "isbn": "9788574481371", + "id": "9788574481371", "titulo": "Contos da Palma da Mão", "autor": "Yasunari Kawabata" }`}
@@ -168,7 +168,6 @@ Response: POST /livros { - "isbn": "9780262510875", "titulo": "Structure and Interpretation of Computer Programs", "autor": "Gerald Jay Sussman" } @@ -176,7 +175,7 @@ POST /livros Response: 201 Created { - "isbn": "9780262510875", + "id": "9780262510875", "titulo": "Structure and Interpretation of Computer Programs", "autor": "Gerald Jay Sussman" }`}
@@ -194,7 +193,7 @@ Response: PUT /livros/9780262510875 { - "isbn": "9780262510875", + "id": "9780262510875", "titulo": "Structure and Interpretation of Computer Programs, 2nd ed.", "autor": "Harold Abelson, Gerald Jay Sussman, Julie Sussman" } @@ -202,7 +201,7 @@ PUT /livros/9780262510875 Response: 200 Ok { - "isbn": "9780262510875", + "id": "9780262510875", "titulo": "Structure and Interpretation of Computer Programs, 2nd ed.", "autor": "Harold Abelson, Gerald Jay Sussman, Julie Sussman" }`} @@ -243,10 +242,10 @@ Response:

@@ -285,13 +284,14 @@ app.Run(); public class Livro { + public long Id { get; set; } public string? Isbn { get; set; } public string? Titulo { get; set; } public string? Autor { get; set; } };`}

- Adicione esta classe no fim do arquivo. Todos os campos são do tipo string?. O ? após o tipo determina a nulabilidade daquela propriedade - ou seja, determina se a propriedade pode receber valores nulos. + Adicione esta classe no fim do arquivo. Todos os campos, com exceção do Id, são do tipo string?. O ? após o tipo determina a nulabilidade daquela propriedade - ou seja, determina se a propriedade pode receber valores nulos. Desta forma, o compilador consegue te auxiliar gerando avisos quando você faz uma referência a uma variável que pode ser nula sem antes verificá-la, o que, se acontecesse, geraria um erro em tempo de execução.

@@ -311,18 +311,21 @@ app.MapGet("/livros", () => { new() { + Id = 1, Isbn = "9780262510875", Titulo = "Structure and Interpretation of Computer Programs", Autor = "Gerald Jay Sussman" }, new() { + Id = 2, Isbn = "9780131103627", Titulo = "C Programming Language: ANSI C Version", Autor = "Dennis Ritchie, Brian Kerningham" }, new() { + Id = 3, Isbn = "9780134190440", Titulo = "The Go Programming Language", Autor = "Brian Kerningham" @@ -450,14 +453,14 @@ Content-Type: application/json

{`// Edita um livro.
-app.MapPut("/livros/{isbn}", (string isbn, Livro livro) =>
+app.MapPut("/livros/{id}", (long id, Livro livro) =>
 {
-    return new { editando = isbn, dados = livro };
+    return new { editando = id, dados = livro };
 });`}

- A url que definimos agora possui um parâmetro definido por "{`{isbn}`}". Isto significa que este pedaço da - url delimitado por chaves pode assumir qualquer valor, por exemplo, PUT /livros/A, PUT /livros/B, etc. + A url que definimos agora possui um parâmetro definido por "{`{id}`}". Isto significa que este pedaço da + url delimitado por chaves pode assumir qualquer valor numérico, por exemplo, PUT /livros/100, PUT /livros/200, etc.

@@ -466,7 +469,7 @@ app.MapPut("/livros/{isbn}", (string isbn, Livro livro) =>

{`### Edita um livro
 
-PUT {{url}}/livros/9780321741769
+PUT {{url}}/livros/1
 Accept: application/json
 Content-Type: application/json
 
@@ -481,17 +484,17 @@ Content-Type: application/json
     
 
     

- Agora, só falta o GET /livros/{`{isbn}`} e o DELETE /livros/{`{isbn}`}: + Agora, só falta o GET /livros/{`{id}`} e o DELETE /livros/{`{id}`}:

{`// Obtém os dados de um livro individual.
-app.MapGet("/livros/{isbn}", (string isbn) =>
+app.MapGet("/livros/{id}", (long id) =>
 {
-    return new Livro() { Isbn = isbn };
+    return new Livro() { Id = id };
 });
 
 // Remove um livro.
-app.MapDelete("/livros/{isbn}", (string isbn) =>
+app.MapDelete("/livros/{id}", (long id) =>
 {
     return Results.NoContent();
 });`}
@@ -502,12 +505,12 @@ app.MapDelete("/livros/{isbn}", (string isbn) =>
{`### Obtém um livro individual
 
-GET {{url}}/livros/9780321741769
+GET {{url}}/livros/2
 Accept: application/json
 
 ### Remove um livro
 
-DELETE {{url}}/livros/9780321741769
+DELETE {{url}}/livros/3
 Accept: application/json`}

@@ -519,5 +522,10 @@ Accept: application/json`}

O código fonte do projeto até agora pode ser baixado aqui.

+ + \ No newline at end of file