atualização bd

This commit is contained in:
Gabriel Almeida Bueno 2025-05-08 08:42:32 -03:00
parent 02531f0861
commit a12908efa6
4 changed files with 121 additions and 115 deletions

View File

@ -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;

View File

@ -20,7 +20,6 @@ h2 {
code {
font-family: var(--font-mono);
font-size: 16px;
}
em {

View File

@ -58,7 +58,8 @@ dotnet add package MySqlConnector`}</code></pre>
O banco de dados que vamos utilizar possui uma tabela com o nome <code>Livro</code>. Esta tabela possui os seguintes campos:
</p>
<pre><code>{`Isbn VARCHAR(255) PRIMARY KEY NOT NULL,
<pre><code>{`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();`}</code></pre>
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
</p>
<p>
O valor de retorno será um <code>IEnumerable&lt;Livro&gt;</code>. Um <code>IEnumerable</code> é uma interface do dotnet que representa
O valor de retorno será um <code>IEnumerable&lt;Livro&gt;</code>. Um <code>IEnumerable</code> é uma interface que representa
qualquer sequência <em>iterável</em> de objetos. Por exemplo, um objeto <code>List&lt;T&gt;</code> ou um vetor <code>T[]</code> são iteráveis,
portanto podem ser retornados neste método.
</p>
@ -215,7 +217,7 @@ public class LivroRepository
var offset = take * Math.Max(pagina-1, 0);
var lista = new List<Livro>();
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();`}</code></pre>
<p>
O <a href="https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/" target="_blank">modelo de programação assíncrona</a> é uma característica que
é praticamente ubíqua no dotnet, mas não precisamos nos aprofundar nela por enquanto. Basta saber que devemos utilizar <code>await</code> 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 <code>await</code> em métodos assíncronos, e
que se o utilizarmos, o nosso método deve ser também assíncrono, sendo declarado com <code>async Task</code>.
</p>
@ -292,7 +295,7 @@ var lista = new List<Livro>();`}</code></pre>
A variável <code>lista</code> é uma lista de objetos <code>Livro</code> que irá guardar todos os resultados da consulta, e depois será retornada.
</p>
<pre><code>{`cmd.CommandText = "SELECT Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro ORDER BY CriadoEm LIMIT @offset,@take";
<pre><code>{`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);`}</code></pre>
@ -312,24 +315,26 @@ cmd.Parameters.AddWithValue("take", take);`}</code></pre>
{
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),
});
}`}</code></pre>
<p>
Este laço é repetido enquanto <code>await reader.ReadAsync()</code> retornar <code>true</code>, 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 <code>reader</code>, como <code>reader.GetString(0)</code>. O número passado como
parâmetro para estas funções indica a posição da coluna lida. Por exemplo, na consulta que realizamos (<code>SELECT Isbn, Titulo, ...</code>), a coluna <code>Isbn</code> é a primeira,
portanto, para ler este valor, devemos executar <code>reader.GetString(0)</code>. <code>Titulo</code> é a segunda, então o seu valor é obtido através de <code>reader.GetString(1)</code>, e assim
parâmetro para estas funções indica a posição da coluna lida. Por exemplo, na consulta que realizamos (<code>SELECT Id, Isbn, Titulo, ...</code>), a coluna <code>Id</code> é a primeira,
portanto, para ler este valor, devemos executar <code>reader.GetInt64(0)</code> (<code>Int64</code>, um número inteiro de 64-bits, é um sinônimo para <code>long</code>).
<code>Isbn</code> é a segunda, então o seu valor é obtido através de <code>reader.GetString(1)</code>, e assim
sucessivamente.
</p>
@ -362,21 +367,21 @@ app.MapGet("/livros", async () =>
Agora execute este endpoint. Se tudo deu certo, você verá alguns livros cadastrados no retorno.
</p>
<h2>Obtendo um livro pelo ISBN</h2>
<h2>Obtendo um livro pela chave primária</h2>
<p>
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.
</p>
<pre><code>{`public async Task<Livro> Obter(string isbn)
<pre><code>{`public async Task<Livro> 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),
};
}`}</code></pre>
@ -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.
</p>
<pre><code>{`cmd.CommandText = "SELECT Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro WHERE Isbn=@isbn";
cmd.Parameters.AddWithValue("isbn", isbn);`}</code></pre>
<pre><code>{`cmd.CommandText = "SELECT Id, Isbn, Titulo, Autor, Genero, Descricao, Foto, Keywords, Ativo, CriadoEm, AtualizadoEm FROM Livro WHERE Id=@id";
cmd.Parameters.AddWithValue("id", id);`}</code></pre>
<p>
A consulta é montada na variável <code>cmd</code>, o parâmetro <code>isbn</code> é adicionado ao comando.
A consulta é montada na variável <code>cmd</code>, o parâmetro <code>id</code> é adicionado ao comando.
</p>
<pre><code>{`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),
};`}</code></pre>
<p>
Assim como na listagem, <code>await cmd.ExecuteReaderAsync()</code> é chamado para ler os resultados da consulta.
Como esperamos que só haja um registro com aquele ISBN, executamos <code>await reader.ReadAsync()</code> apenas uma vez.
Se este método retorna <code>false</code>, é 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 <code>await reader.ReadAsync()</code> apenas uma vez.
Se este método retorna <code>false</code>, é 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 <code>Livro</code> que será retornado.
</p>
@ -448,10 +455,10 @@ return new()
</p>
<pre><code>{`// 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;
});`}</code></pre>
@ -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 <code>livro</code> para garantir que nenhum deles seja nulo, já que no banco de dados, todos os campos da tabela são <code>NOT NULL</code>.
</p>
<pre><code>{`if (livro.Isbn == "")
{
throw new Exception("O ISBN do livro é obrigatório.");
}
if (livro.Titulo == "")
<pre><code>{`if (livro.Titulo == "")
{
throw new Exception("O título do livro é obrigatório.");
}`}</code></pre>
@ -635,14 +632,14 @@ app.MapPost("/livros", async (Livro livro) =>
O método de edição é similar ao de criação.
</p>
<pre><code>{`public async Task<Livro> Editar(string isbn, Livro dados)
<pre><code>{`public async Task<Livro> 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.
</p>
<pre><code>{`var livro = await Obter(isbn);
<pre><code>{`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;`}</code></pre>
<p>
Chamamos a função <code>Obter(string)</code> que criamos para obter do banco de dados o livro que será editado. Em seguida, atribuímos a este objeto
Chamamos a função <code>Obter(long)</code> que criamos para obter do banco de dados o livro que será editado. Em seguida, atribuímos a este objeto
os valores do objeto <code>dados</code>, formatando-os devidamente.
</p>
@ -696,10 +693,10 @@ livro.AtualizadoEm = DateTime.Now;`}</code></pre>
@"
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;`}</code></pre>
</p>
<pre><code>{`// 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;
});`}</code></pre>
@ -737,15 +734,15 @@ app.MapPut("/livros/{isbn}", async (string isbn, Livro livro) =>
Portanto, o método de remover será basicamente uma edição.
</p>
<pre><code>{`public async Task Desativar(string isbn)
<pre><code>{`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();
}`}</code></pre>
@ -755,11 +752,11 @@ app.MapPut("/livros/{isbn}", async (string isbn, Livro livro) =>
</p>
<pre><code>{`// 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);
});`}</code></pre>
<h2>Finalizando</h2>

View File

@ -114,7 +114,7 @@ Donald Knuth - The Art of Computer Programming`}</code></pre>
</section>
<p>
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:
</p>
<pre><code>{`Request:
@ -125,7 +125,7 @@ Response:
Yasunari Kawabata - Contos da Palma da Mão`}</code></pre>
<p>
Note que agora a URI ficou <code>/livros/<b>9788574481371</b></code> onde <code><b>9788574481371</b></code> é o ISBN do livro, é um dado que o identifica e pode ser uma chave primária.
Note que agora a URI ficou <code>/livros/<b>9788574481371</b></code> onde <code><b>9788574481371</b></code> é a chave primária do livro, o dado que o identifica.
</p>
<p>
@ -140,7 +140,7 @@ Response:
200 OK
<livro>
<isbn>9788574481371</isbn>
<id>9788574481371</id>
<titulo>Contos da Palma da Mão</titulo>
<autor>Yasunari Kawabata</autor>
</livro>`}</code></pre>
@ -155,7 +155,7 @@ GET /livros/9788574481371
Response:
200 Ok
{
"isbn": "9788574481371",
"id": "9788574481371",
"titulo": "Contos da Palma da Mão",
"autor": "Yasunari Kawabata"
}`}</code></pre>
@ -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"
}`}</code></pre>
@ -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"
}`}</code></pre>
@ -243,10 +242,10 @@ Response:
<ul>
<li><code>GET /livros</code> para obter todos os livros no sistema;</li>
<li><code>GET /livros/{`{isbn}`}</code> para obter um único livro, identificado pelo seu ISBN;</li>
<li><code>GET /livros/{`{id}`}</code> para obter um único livro, identificado pela sua chave primária;</li>
<li><code>POST /livros</code> para inserir um novo livro;</li>
<li><code>PUT /livros/{`{isbn}`}</code> para editar um livro;</li>
<li><code>DELETE /livros/{`{isbn}`}</code> para remover um livro.</li>
<li><code>PUT /livros/{`{id}`}</code> para editar um livro;</li>
<li><code>DELETE /livros/{`{id}`}</code> para remover um livro.</li>
</ul>
<p>
@ -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; }
};`}</code></pre>
<p>
Adicione esta classe no fim do arquivo. Todos os campos são do tipo <code>string?</code>. O <code>?</code> após o tipo determina a <em>nulabilidade</em> 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 <code>Id</code>, são do tipo <code>string?</code>. O <code>?</code> após o tipo determina a <em>nulabilidade</em> 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.
</p>
@ -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
</p>
<pre><code>{`// 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 };
});`}</code></pre>
<p>
A url que definimos agora possui um <em>parâmetro</em> definido por <code>"{`{isbn}`}"</code>. Isto significa que este pedaço da
url delimitado por chaves pode assumir qualquer valor, por exemplo, <code>PUT /livros/A</code>, <code>PUT /livros/B</code>, etc.
A url que definimos agora possui um <em>parâmetro</em> definido por <code>"{`{id}`}"</code>. Isto significa que este pedaço da
url delimitado por chaves pode assumir qualquer valor numérico, por exemplo, <code>PUT /livros/100</code>, <code>PUT /livros/200</code>, etc.
</p>
<p>
@ -466,7 +469,7 @@ app.MapPut("/livros/{isbn}", (string isbn, Livro livro) =>
<pre><code>{`### 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
</div>
<p>
Agora, só falta o <code>GET /livros/{`{isbn}`}</code> e o <code>DELETE /livros/{`{isbn}`}</code>:
Agora, só falta o <code>GET /livros/{`{id}`}</code> e o <code>DELETE /livros/{`{id}`}</code>:
</p>
<pre><code>{`// 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();
});`}</code></pre>
@ -502,12 +505,12 @@ app.MapDelete("/livros/{isbn}", (string isbn) =>
<pre><code>{`### 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`}</code></pre>
<p>
@ -519,5 +522,10 @@ Accept: application/json`}</code></pre>
<p>
O código fonte do projeto até agora pode ser baixado <a href="https://git.gbrl.dev/Gabriel/Biblioteca/archive/etapa2.zip">aqui</a>.
</p>
<nav>
<span>Próximo:</span>
<a href="/bd">Conectando com o banco de dados</a>
</nav>
</section>
</section>