Transcrições
1. Introdução: Bem-vindo a este novo curso Entity Framework
Core, um tour completo. Meu nome é Trevor Williams e sou
engenheiro de software e palestrante com mais de dez anos de experiência
no desenvolvimento de aplicativos, além de ensinar
pessoas a fazer Neste curso,
você aprenderá sobre o Entity Framework Core, e essa é a principal estrutura de acesso a
dados da Microsoft ou ORM para dot t. Agora,
neste curso, abordaremos
algumas coisas que o colocarão acima e além de
seus colegas em termos de como
você interage com
seus bancos
de dados ao Vamos explorar a estrutura de
entidades e como ela ajuda você a criar
aplicativos mais rapidamente em.net, bem
como como ela
ajuda a gerenciar a criação e as alterações do
banco de dados
usando simplesmente a sintaxe C sharp Isso mesmo. Usando a
entidade Framework Core. Você não
precisa necessariamente usar SQL
ou ir ao estúdio de
gerenciamento
para manipular seu banco de dados
e, ao final deste curso,
terá uma
boa compreensão de
como tudo isso é gerenciado por meio de migrações, do contexto do banco de dados
e
dos modelos de banco de dados Você entenderá
como escrever consultas de link para interagir com seus
objetos e tabelas de banco de dados, além de explorar muitos
outros recursos avançados núcleo
do Entity Framework Agora, ao final deste curso, você deve
estar familiarizado com a estrutura de
entidades e como ela permite que você
escreva consultas de links e interaja com seus dados Um pouco de história sobre a estrutura de
entidades. Ele está em desenvolvimento
desde 2008 no DottFramework, mas evoluiu e evoluiu e
evoluiu e momento, estamos no D
cinco ou no Dt COR cinco Portanto, a biblioteca, que está atualmente em uso em um estado estável, é a EF Core five, que é o que
exploraremos. No entanto, em breve
haverá EFC six, e a maior parte do que
aprenderemos aqui será conhecimento
transferível Agora, um pouco mais
sobre o que é o EF COR. É um
mapeador relacional de objetos. Eu usei a sigla ORM anteriormente. É isso que significa. Mapeador relacional de objetos. Portanto, é uma biblioteca de
código aberto com APIs que
facilitam a interação
com o banco de dados Embora usemos o SQL
Server neste curso, muitos recursos do FCRs
podem ser estendidos para outros bancos de dados, como post
resca e cuaide and my ca. Portanto,
aprender C
traz muitos benefícios , pois isso Isso ajuda você a reduzir a
repetição de código e permite que você se
concentre em outras coisas em
seu aplicativo mantendo a
base de código agradável e
consistente por toda parte Também está
pronto para uso corporativo. Isso mesmo. Se você está criando um
aplicativo grande e está preocupado em ter
muitas consultas e
ter código mesic, FCR é perfeito para você porque
é bom e compacto Ele permite que você mantenha
a sintaxe em C nítida e é estável o suficiente para
funcionar em condições extremas Eu sei que você está vendo
este curso e se perguntando, esse curso
é realmente para mim? Bem, se você quiser aprender sobre o FCR, você está no lugar certo Se você conhece um pouco de C sharp e tem algum conhecimento
de banco de dados, você está no lugar certo. Se você quiser aprender formas
modernas de interagir com seu banco de dados
usando tecnologia, você
definitivamente está
no lugar certo Ao final deste
curso, você
não terá fraquezas
nem ameaças Você só pode ficar
cada vez melhor. Então, o que você está esperando? Estou feliz em ter
você neste curso e nos vemos
na próxima palestra.
2. Ambiente de desenvolvimento de configuração: Ei, pessoal, bem-vindos de volta.
Então, nesta lição, vou explicar o que
você precisa para configurar seu ambiente
para este curso. Então, eu já estou aqui no site do
Visual Studio, você pode chegar lá dizendo
sutudo.microsoft.com E o que vamos
usar é a edição
comunitária
do Visual Studio IDE. Não, esse é o
principal IDE fornecido pela Microsoft
para o
desenvolvimento.NET Portanto, é perfeito
para este curso. No entanto, se você não
conseguir usar essa edição comunitária, em uma máquina Windows
e estiver usando um MAC, eles terão a versão MAC. Se você não estiver usando um MAC, poderá usar o código do
Visual Studio, que também é de código aberto
totalmente gratuito e está disponível em todos os sistemas operacionais. Agora, as coisas que
farei neste curso serão diferentes se você estiver usando o código do
Visual Studio, mas farei o possível para fazer
anotações ao longo do caminho para tentar garantir que
você seja capaz de
realizar as operações. Agora, depois de baixar o
Visual Studio, você receberá bem, pelo
menos baixando
o instalador Depois de iniciar este instalador, você receberá uma
tela semelhante a esta. Agora, eu já o tenho
na minha máquina, e o que você está vendo são
as diferentes cargas de trabalho que
eu já instalei Você não precisa de tantos
para este curso em particular. Se você já tem os
que estou prestes a mostrar, pode seguir em frente
e pular esta etapa Mas se você está aqui e precisa
saber o que comprar. Você precisa dessa carga de trabalho de desenvolvimento
multiplataforma do.net, que nos fornece, na
verdade, as bibliotecas básicas
para
o desenvolvimento do.net core E faremos uma
pequena atividade na web. Portanto, seria uma boa
ideia obter
também a carga de trabalho de
desenvolvimento web e de rede do AP Então, no mínimo,
você precisa desses dois. Quanto mais você clicar, é claro, mais coisas serão instaladas, então você não
precisa clicar em tantas quanto você me vê marcando aqui Portanto, o desenvolvimento de rede e web da AP , bem como o desenvolvimento
multiplataforma do.net Portanto, você pode prosseguir
e instalá-los. Agora, você precisa concluir esta etapa, especialmente se não estiver usando o Visual Studio e
uma máquina Windows, porque se for usar o código do Visual Studio, precisará instalar
o SDK em segundo plano Isso vem com o
Visual Studio, certo? Mas se você não estiver usando o
Visual Studio novamente, você pode
baixar esse SDK, então você pode simplesmente
chegar aqui acessando a Microsoft co. E
a partir dessa página de destino, você poderá navegar página
de downloads.t5, onde obterá esse Você também pode ir em frente e obter os tempos de execução porque
precisamos deles para hospedagem,
mas, no mínimo,
você precisa desse SDK OK. Agora, depois de tudo ter
sido instalado e configurado, você só quer ter certeza de
que tudo está instalado. Então você pode ir ao
seu prompt de comando, seja qual for o sistema operacional, e então você pode simplesmente
digitar.net H. Então, ao fazer isso,
você verá se estiver vendo uma impressão na tela
parecida com esta
, você está no caminho certo Portanto, ele informará a versão do
SDK que você tem e mostrará todos
os diferentes comandos
que você pode usar Portanto, você pode realmente usar
esses comandos ao criar um novo aplicativo.NET
core
e, especialmente mais uma vez, se estiver usando o código do
Visual Studio, definitivamente
usará um pouco mais
os comando.net Tudo bem. Então, isso é realmente tudo para configurar
o ambiente. Este é um vídeo de cinco minutos, mas
provavelmente levará algumas horas ou mais minutos se você estiver
configurando do zero, mas não demorará muito. Então, assim que
terminar e verificar se
tudo está instalado, você pode passar para
a próxima lição.
OK.
3. Configurando a solução: Ei, pessoal, bem-vindos de
volta nesta lição, vamos começar a configurar nossa solução para o
projeto ou para este curso. E o que vamos fazer é começar com uma solução em branco. Então, vou
clicar em Criar novo projeto e vou pesquisar
o modelo de solução em branco. E esse é o que
vamos selecionar. Então vá em frente, clique em Avançar. E vou
chamar a solução chamada entity framework net five, certo, indicativa do
curso que estamos fazendo E com minha localização definida,
vou clicar em criar. E assim,
temos o Visual Studio com nosso arquivo de solução em branco. O que vamos
fazer é
começar adicionando um novo
projeto à solução. Então, vou adicionar um novo projeto
e, em seguida, vou adicionar um aplicativo de console porque
vamos usar um aplicativo de console para analisar os fundamentos
do núcleo da estrutura de
entidades Certo? Antes de entrarmos em toda a empolgação da web
e disso e daquilo,
quero que entendamos
o que o FCR pode fazer, porque se o
entendermos a partir de um aplicativo de console
, as possibilidades
são ilimitadas quando precisamos criar aplicativos mais
complicados Então, vamos continuar, clicar em
Aplicativo de console, clicar em Avançar e
chamaremos isso de aplicativo de console net five de
estrutura de entidade . Então vá em frente, clique em Avançar novamente. objetivo é cinco
como nossa estrutura de metas
e, em seguida, vamos em frente e criamos e, em seguida, vamos em frente e criamos OK. Agora que nosso aplicativo de
console foi criado. Vamos criar mais
dois projetos, e esses realmente serão bibliotecas
de classes. Agora, no desenvolvimento corporativo, um dos
princípios fundamentais é a separação de interesses, significa que temos o aplicativo, que provavelmente
vai mexer os cordões,
conversar com o usuário Mas então precisamos de outros projetos em que armazenaremos objetos relacionados ao banco de dados e as configurações relacionadas ao
banco de dados sejam separadas É por isso que estamos adicionando mais
dois projetos na
forma de biblioteca de classes. Então, eu tenho
a biblioteca da classe à esquerda aqui. Você sempre pode rolar, mas pode pesquisar se
precisar e
lembre-se sempre de que estamos lidando
com C sharp. Tudo bem? Então, para a biblioteca de classes, vamos chamar
essa primeira estrutura de uma entidade de dados
líquidos de cinco pontos. E então a
estrutura de destino ainda está em cinco
e, em seguida, clicamos em Criar. E por último, mas não menos importante, vamos
adicionar mais uma biblioteca de classes, e essa será
o domínio de pontos. Então, a mesma
convenção de nomenclatura que temos domínio líquido de
cinco pontos do framework de
entidades, certo? E ainda é uma estrutura de
alvo.t5, e então vamos adicionar Então, isso é realmente tudo
para a configuração da nossa solução. Então, mais uma vez,
vamos operar
com três projetos, pelo
menos agora, três projetos
diferentes. Este, o aplicativo de console
listando-o como a interface do usuário, você pode vê-lo aqui como um tipo de
saída de executável Portanto, ele sabe que deve executar ou
fazer alguma coisa. É assim que a
configuração principal ou os arquivos do projeto são configurados, porque
se você olhar para este de forma diferente
da biblioteca de classes, verá que este
tem apenas a estrutura de destino. Este sabe que é a estrutura de
destino e o fato de
ser um executável Essa é a única diferença material
entre os dois, certo? Então, este representará onde
escreveremos nosso código prático, mas depois configuraremos nosso domínio e
objetos de dados aqui. Bem, o domínio terá nossos modelos de
dados para classes
e, em seguida, os dados terão nossas configurações
e arquivos de dados Então, quando chegarmos,
começaremos a nos divertir e começaremos a modelar
algumas das tabelas que
usaremos neste curso.
4. Como criar modelos de dados com EF Core: Vocês são bem-vindos de volta.
Então, nesta lição, vamos começar a modelar
nossas tabelas de banco de dados. Agora, o que eu tenho na tela é um diagrama de banco de dados ou diagrama de relacionamento de
entidades ERD Ela tem alguns nomes, e há algumas
representações dela. Mas o conceito fundamental é que é um diagrama que mostra as diferentes entidades
ou tabelas dentro de um banco de dados e qual é a coluna da chave
primária, quais são os outros campos
e, em seguida, mostra que
existe o que chamamos relação
de chave estrangeira
entre duas tabelas Aqui, está mostrando que
temos equipes e ligas Essas são duas mesas. A liga tem um ID, que vamos transformar um
número inteiro de incremento automático e tem um nome E então uma equipe também tem um ID, também como nome,
mas depois tem um ID da liga. Esse ID da liga é o que
chamamos de chave estrangeira
para a liga. Uma equipe pertence a uma liga. Esse é o relacionamento. Se você está familiarizado
com banco de dados, então você já
sabe o que está acontecendo. Se você não está tão familiarizado
, isso não é problema. Espero que você entenda pelo
menos o conceito por trás desse diagrama. Tudo bem O que queremos fazer, porém, é configurar tabelas como
essa dentro do EFC Queremos usar o FCO para
modelar um banco de dados que
gerará essas tabelas Portanto, você tem
convenções diferentes quando se
trata de desenvolver
em cima de um banco de Então, podemos fazer isso primeiro com o banco de dados, ou
seja, alguém
projetou o banco de dados e tudo mais e depois começamos a
criar o
aplicativo, ou você tem o código primeiro, o
que, embora implique que o código vem primeiro, o
que realmente significa é que vamos
escrever o código que é então
transformado no banco de dados. Dessa forma, se precisarmos mudar
alguma coisa no futuro, na verdade, apenas
alteramos o código
e, em seguida, podemos deixar que isso faça alterações incrementais no banco
de dados definido E o EFC suporta qualquer um deles.
Essa é a beleza disso. Portanto, na maior parte
deste curso, examinaremos
primeiro o código e como podemos fazer alterações
marginais ou
incrementais medida que avançamos
modificando Mas veremos como
fazer engenharia reversa um banco de dados existente em
um conjunto de arquivos EFC, certo? Então chega de falar,
vamos falar sobre isso. Então, meus modelos de dados ou modelos
de
domínio
acabarão entrando no
projeto de domínio, certo? Então, vou me livrar
dessa classe padrão
que obtivemos com ela, e vou adicionar
uma nova classe, e vou chamar
essa classe de liga. Agora, de um modo geral, eu
sempre aconselho meus alunos , sempre
que você estiver
criando um banco de dados, tente começar
com aqueles com menos dependências
e depois continuar porque você não quer
criar uma tabela que tenha duas ou três
chaves estrangeiras relacionadas a outras tabelas e essas
tabelas ainda não existem Já que nessa situação, a
Liga é uma tabela independente, que significa que a liga está lá Uma liga existirá pelo
menos agora
sem nenhuma equipe, mas a equipe
depende da liga. Eu quero que a liga exista primeiro. Crie essa classe,
vou torná-la pública para que outros
projetos possam acessá-la. E então, dentro disso, eu vou ter as duas
propriedades, ID e nome. Então, vamos dizer public
int ID, nome da string pública. Veja aqui,
especialmente se você estiver familiarizado com os tipos de
dados em SQL, você verá que não estamos vendo Var char aqui. Estamos
dizendo string. FCR será capaz de traduzir o C sharp nativo
de quais tipos de dados Nos tipos de dados
SQL equivalentes. Veremos isso mais tarde. Esse é um dos benefícios. Podemos usar nosso C sharp nativo dentro de nosso aplicativo FCO, e a tradução para
o banco de dados
acontecerá de forma anônima para nós Outra
coisa importante a ser destacada são as convenções de nomenclatura e o suporte que você recebe do FCO ao seguir modo geral, uma coluna
de ID será chamada de ID. Às vezes, você pode se qualificar e dizer o ID da liga ou
o ID do nome da mesa Agora, o COR identificará qualquer
uma dessas convenções e
inferirá automaticamente que essa
deve ser sua chave primária e uma coluna de
identidade QL com
incremento automático identidade QL com
incremento automático Então, ele verá automaticamente essa convenção de nomenclatura e dirá ao SQL que essa é
a coluna da chave primária Portanto, se você se desviar dessa convenção
geral de nomenclatura, precisará fazer
configurações adicionais para
que isso funcione Então, para mim, é mais fácil
trabalhar apenas com o FCR do que forçar o cabo F
em outra passagem Não é a
coisa mais difícil de fazer, mas por que
trabalhar mais quando pode ser tão fácil Apenas dizendo ID, você
saberá que essa é a chave primária e
ajustará todo o resto para mim. Agora, vou criar a próxima tabela ou
a próxima classe representar a
próxima tabela, que é a equipe. Estou apenas adicionando isso
ao projeto de domínio. Equipe é o nome e
, mais uma vez, a equipe pública também
terá ID e nome. Como vimos, mas depois
tem uma terceira coluna, que é o ID da liga. Isso representa uma chave estrangeira. Agora, o que vamos fazer
quando temos uma chave estrangeira, temos que adicionar duas propriedades. Um, sendo o nome da tabela ou o nome da
tabela para a qual essa é uma chave estrangeira e o ID. Mais uma vez, convenção de nomenclatura. A segunda seria uma propriedade
de navegação e, na maioria das vezes, você
os verá tornando isso virtual. Vamos apenas adicionar isso. A liga
virtual pública tipo de
dados da classe que
acabamos de criar com o mesmo nome. Isso é bom. Mas
a combinação delas fará com que F deduza que essa correspondência entre o nome da
tabela e a palavra ID significa que essa é uma chave
estrangeira para essa tabela Tudo bem Então, se
você teve que configurar uma chave estrangeira no SQL Server, você sabe que
precisa entrar e escolher as colunas, fazer
isso e aquilo .
E
há algumas etapas. Isso é tudo o que é preciso. Siga
a convenção de nomenclatura e tenha essa propriedade
de navegação E o FCO apenas dirá:
Ok, eu sei que essa
é uma chave estrangeira e sei que
posso incluir ou
apresentar automaticamente os detalhes relacionados
a esse registro por meio
dessa propriedade Mais tarde, veremos isso de uma só vez para mostrar muitas informações. Mas estou apenas tentando
mostrar que, desde o início, depois de seguir essas convenções
fundamentais de nomenclatura, o
FCR fará grande
parte do trabalho por você FCR fará grande
parte do trabalho Ok. Então,
na verdade, é isso por enquanto. Criamos as classes que deveriam representar
as tabelas no banco de dados. Obviamente, os nomes das colunas que
correspondem aos tipos de dados são conceitualmente iguais ao que esperaríamos que fossem no
banco de E mais tarde, quando
voltarmos, veremos como
configuramos o contexto do banco de dados,
o provedor e a conexão
real com
o banco
de dados, porque nada disso existe no momento. Não há banco de dados. Estamos apenas modelando isso e dizendo:
Bem, eles representam
o que eu quero armazenar. Então, quando
voltarmos, veremos como
realmente configuramos o
link para o banco de dados. Ok.
5. Especializando o provedor de dados e string de conexão: Nosso pessoal estava de volta e o objetivo desta
lição é configurar nossa classe de dados para
que ela saiba que precisa
se conectar ao
nosso banco de dados. Tudo bem Então, nossa classe de dados, teremos que adicionar
algumas bibliotecas a ela para permitir ela realmente interaja
com essa estrutura de rede. Desculpe, com a estrutura de entidades. Porque, no momento,
ninguém sabe nada. Estamos apenas falando
sobre estrutura de entidades. É chamado de estrutura de entidades, mas não sabe nada
sobre estrutura de entidades. Então, deixe-me começar
excluindo essa classe padrão, e vou entrar nos novos pacotes de portas e vamos até
Bros
e vamos pesquisar servidor SQL
principal do
Entity Framework Então, antes de prosseguir e instalar isso logo de cara,
deixe-me explicar. Você tem a
entidade Microsoft Framework Core. Essa é a
biblioteca base para todos. Acho que toda variação
depende dessa. Se você observar, é
um
mapeador moderno baseado em objetos para.it suporta
consultas de links, rastreamento de alterações
e funciona com
vários bancos de dados, servidor CQL, Azure,
posters CQight O que você percebe
é que, a partir do UGT, você pode realmente obter bibliotecas
diferentes para suportar os
diferentes bancos de dados No nosso caso, estamos usando o servidor
Microsoft k. Mas se eu fosse pesquisar o núcleo da estrutura de
entidades e apenas examinar as
diferentes variações que vemos em nosso servidor k, vemos na memória, vemos cQight Você vê o Postgres, você
vai ver o MCL. Não vou
examinar todos eles,
mas a questão é que,
seja qual for o banco de mas a questão é que,
seja qual for o banco que você tenha nos bastidores, é mais do que
provável que
haja uma biblioteca para apoiá-lo e você pode
obtê-lo no New gt. Tudo bem Como eu disse, hoje estamos trabalhando apenas
com o SQL Server, então vamos prosseguir
e instalar esse, então vou
baixá-lo. E, ao fazer isso, ele
mostrará todas
as outras dependências que ele tem, certo? Mas tudo bem. Podemos simplesmente clicar em OK, aceitar qualquer
contrato de licença e permitir que você o
instale em nosso projeto. Então, agora que ele está
instalado em nosso projeto. Se eu olhar para trás no arquivo CSP, basta clicar no arquivo
do projeto para obter os dados do projeto de dados Você verá aqui que agora temos essa
referência de pacote instalada. Como alternativa, você também
poderia ter seguido em frente e colocado essa
linha semelhante a esta. Ele poderia dizer a referência
do pacote node, incluir o nome da biblioteca, a versão na qual
você está interessado
e, em seguida, apenas
criar, e ele
automaticamente obterá as dependências para você Então, ele poderia ter feito isso também, mas vamos continuar usando o NewG Então eu posso fechar tudo isso. E a próxima coisa na agenda
seria criar o que
chamamos de contexto de banco de dados. Então, eu quero criar
outra classe e, em seguida, vou chamar essa classe de contexto da liga de futebol da liga futebol ou contexto de banco de dados da liga de
futebol. Nós tendemos a colocar isso em contexto do
banco de dados significa apenas que é o contexto ou a conexão. Digamos que contexto é
igual a conexão. Contexto de banco de dados significa arquivo de
conexão de banco de dados, por assim dizer. E então isso só
permite que você saiba qual banco de dados é. Não é uma
convenção de nomenclatura em si. É assim que eu estou fazendo
isso. Só estou explicando por que estou
chamando assim Então, vou criar esse contexto de banco de dados de classe
pública pública
e, em seguida, cada contexto
de banco de dados herdará do contexto de banco de dados padrão
proveniente do núcleo EF Então você tem contextos de
banco de dados diferentes, você tem contexto de banco de dados, você tem contexto de banco de dados de identidade se quiser a autenticação do usuário Mas, por enquanto, vamos nos ater
ao contexto básico do banco de dados, controle e ao ponto e, em
seguida, isso me
informará que preciso de uma
declaração de uso para a estrutura de entidades. Núcleo. Agora isso está satisfeito. Eu posso contar isso sobre as mesas. Lembre-se de que isso
representará a conexão com
o banco de dados. Então, tudo o que está
no banco de dados precisa
ser representado aqui. Temos os modelos que representam as tabelas
no banco de dados. Agora que temos o link
para o banco de dados, precisamos informar esse link
sobre as tabelas. Então, eu quero dizer conjunto de banco de dados público. E esse conjunto de banco de dados significa
apenas que o conjunto de linhas ou registros é, na verdade,
uma tabela no banco de dados. Você é o modelo da
equipe. Tudo bem. E seu nome é equipes. Então, você pode ler assim
, basta dizer que entenda exatamente o que você está
digitando à medida que avança Não, eu preciso ter uma dependência. Preciso adicionar uma referência
ao projeto de domínio aqui. Então, eu vou clicar nele,
mas eu já tive problemas
com isso antes,
então vou fazer
isso manualmente, clicar em dependências,
adicionar referência de projeto e , em
seguida, adicionar o projeto de domínio,
clicar, e então podemos seguir em frente e usar nossas
instruções de uso Então, vou
duplicar essa linha e fazer a mesma coisa para uma liga que o banco de dados definiu para
a liga, que estamos chamando de ligas
no Eu tenho um conjunto de banco de dados
para objetos de equipe, estamos chamando isso de equipes. Isso, mais uma vez,
gerará ou interagirá com
uma tabela chamada equipes, e tudo o que estiver
na tabela de equipes será serializado ou convertido em uma
classe de equipe nativa que definimos A próxima coisa que quero fazer é realmente informá-lo
sobre um banco de dados, e precisamos fazer o que
chamamos de
string de conexão para isso. Portanto, as cadeias de conexão geralmente, como em um aplicativo da Web, elas seriam transmitidas, então você tem a string de conexão
no aplicativo da Web e ela é transmitida por meio configurações
para o contexto Não temos esse
luxo no momento, então vamos fazer isso manualmente, então vou escrever override E então, o fato é
que o contexto do banco de dados, que é nossa classe EFC,
vem com várias funções que podemos realmente sobrescrever
e Mas o que me interessa
é configurar. Isso significa que sempre que você estiver
configurando o contexto do banco de dados, o que você quer que eu faça? Eu vou substituí-lo. Não preciso substituir nada na base ou
interagir com a base,
mas vou
dizer que o servidor UCL do construtor de
opções Você vê que isso é cortesia
do nosso servidor de pontos, biblioteca
FCR, biblioteca
FCR Então, servidor UeQL. E vamos colocar nossa
cadeia de conexão aqui. Como esse é um aplicativo de demonstração nos estágios iniciais, estamos
fazendo tudo isso. Mas é claro, estou
orientando você para que você entenda por que estamos
fazendo isso dessa maneira. Portanto, uma cadeia de conexão
compreende algumas partes. Vamos dizer que a
fonte de dados é igual a, e então
especificaríamos o servidor. Então, vou usar o banco de dados local, que é um servidor local
incorporado ao Visual Studio, e você pode acessar
bancos de dados locais por meio do explorador de objetos do SQL
Server, que você pode acessar e pronto. Tudo bem Local D B, barra invertida, barra invertida
e, em seguida, vamos dizer SQL local D B.
Acerte
a Acerte Reserve um tempo para obtê-lo exatamente
como você vê aqui, mesmo com parênteses
e tudo mais,
a barra invertida
dupla e tudo a barra invertida
dupla Em seguida, temos
o catálogo inicial e esse é basicamente o
nome do banco de dados. Como estamos chamando
o banco de dados? Vou chamá-lo de FCR, sublinhado
da Football League. Essa é a nossa
cadeia de conexão. Tudo bem E com isso, concluímos
a configuração do provedor de dados e a configuração do link
para o banco de dados. Agora, é claro, esse banco de dados ainda
não existe, certo? Então, eu criei um link para algo que praticamente não está
lá. E eu disse que essas tabelas
precisam existir em um banco de dados definido, que, como acabamos de
dizer, não existe. Então, vou dar uma olhada
no explorador de servidores SGO rapidamente para mostrar que ele realmente
não existe lá Eu tenho alguns bancos de dados de teste
e, como você pode ver
, eles não estão lá. Então, quando voltarmos, o que
faremos usando o FCO para gerar esse banco de dados para
que possamos começar a
interagir com
6. Migrações e criação de banco de dados: Ei, pessoal, bem-vindos de volta.
Então, na última lição configuramos nosso contexto de DV,
que, como eu disse, é nossa
conexão com o banco de dados Nesta lição,
começaremos a analisar as migrações, que são nossas instruções
para o banco Nossa primeira migração será
criar o banco de dados porque
uma migração sempre dirá o que existia, o que existe agora? O que é diferente? Deixe-me dar instruções para
fazer essas mudanças. Neste momento, não há nada. Então, o que está lá agora não é nada, e então as instruções
gerarão o que deveria estar lá. Certo? Então, para
fazer nossas migrações, precisamos de outra ferramenta dos
nossos novos pacotes de portas, e essa biblioteca é
literalmente ferramentas, certo? Precisamos do FC dois.
Vá até New Gate, vou clicar em
ferramentas e fazer o download
dessa, que vem
automaticamente com o design
e algumas outras bibliotecas, mas vou
deixar que ela seja instalada. Depois de instalar isso, terei
que definir uma
referência de projeto entre o console e nosso projeto de dados porque quando executamos um comando
para atualizar o banco de dados, precisamos executá-lo no projeto inicial
ou no projeto principal,
e o projeto principal precisa
saber sobre os outros
projetos com,
você sabe, a conexão e
o contexto do banco de dados e assim por diante. Então, vou
adicionar uma referência de projeto
ao console para ambos, porque
precisaremos ser capazes de acessar os objetos do domínio. Também precisamos
ser capazes de acessar o domínio e o
contexto do banco de dados, certo? Então, vou
acrescentar isso E depois, sabendo que
tudo isso está feito, podemos executar uma migração. Para executar migrações
usando o Visual Studio, queremos acessar o console do gerenciador de
pacotes Assim, você pode acessar as ferramentas, obter o gerenciador de pacotes e
ver o console do gerenciador de pacotes. tenho o
meu disponível Já tenho o
meu disponível
aqui neste painel
e, claro, você pode
mover todos os painéis para cima. Deixe-me refazer esse. Agora, antes de começarmos
as migrações, eu só quero que
vejamos a extensão das opções disponíveis para nós Neste console do gerenciador de pacotes, posso dizer get hip and
help e ,
em seguida, digitar a estrutura de entidade, aguardar
alguns segundos
e, em seguida, ele
gerará um bom documento mostrando tudo o que é
possível por meio da estrutura de
entidades. Ele começa com um unicórnio e nos fala
sobre a biblioteca Ele nos dá todos os comandos e para que eles são usados A mesma lista que
acabei de indicar no GT, está disponível aqui
com a documentação. Então, como eu disse,
adicionaremos uma migração
e, em seguida, teremos que atualizar o banco de dados após
cada migração. Eu mencionei anteriormente
que você tem código primeiro versus o
banco de dados primeiro. Então, se você está fazendo código primeiro,
bem, esse é o banco de dados de atualização de adição de
migração. Se você estiver criando o banco de dados primeiro, então você gostaria de
escanear o contexto do FO DB, o que basicamente diz: estou
examinando o banco de dados e gerando os modelos de classe com base no que vejo
no banco de dados Então você vê que eles têm
algumas opções disponíveis. Você pode criar um script para o contexto de DV e
para as migrações. Se você ainda é antiquado
para gerar a migração, você quer um script SQL Você pode fazer tudo isso
usando essas ferramentas. Então, vamos em frente. Vou apenas
limpar esse CLS, limpar aquele console e, seguida,
saberei adicionar uma migração Portanto, o
projeto padrão, mais uma vez, precisa ser o
projeto em execução na solução E eu vou
dizer que adicione a migração. E então eu vou
dar um nome a ele. Então, o nome, normalmente, você quer usar um nome
sensato o suficiente para você ou outra pessoa. Bem, vamos começar
com outra pessoa. Outra pessoa pode
aparecer e dizer: Ok, essa é a
ideia geral dessa migração. Você também quer
usar um nome sensato porque depois de sair de
férias e voltar, você quer
relembrar essa migração e entender por que ela foi
feita e para que servia Portanto, não chame a migração de X ou apenas algo tolo,
dê algum significado a ela Então, como se não houvesse nada aqui. Não tenho migrações,
não tenho banco de dados. Ainda. Eu quero chamar isso
de migração inicial. Eu também gosto de colocar meus nomes em
camelo. Quando você usa espaços
, precisa tomar
precauções extras ao reutilizar os
nomes e assim por diante Então eu só uso casaco de camelo. Você pode usar
sublinhados, qualquer coisa, mas eu simplesmente não gosto de espaços
dentro desses nomes Então, vou
adicionar essa migração. Ele construirá o projeto e a construção será bem-sucedida, mas eu tenho um erro. Então, vamos ler esse erro.
E neste curso, não
vou me esquivar
de cometer erros porque sei que muitas pessoas odeiam os erros que
cometem no EFC Às vezes, eles
não são muito claros e é difícil solucionar
alguns desses erros Então, eu não vou me
esquivar de erros. Na verdade, conjurarei
deliberadamente alguns erros para que possamos resolvê-los
juntos Mas isso é
simplesmente dizer que
o projeto de startup,
que é o aplicativo do console, não faz referência ao projeto de
design, certo? Então, em outras palavras, preciso
instalar um pacote
no aplicativo do console. Então, uma maneira fácil de fazer isso. Claro, você pode
ir para New gate, mas vou tentar fazer
isso por meio do arquivo do projeto. Vou criar um novo grupo de
itens e fornecer a ele uma referência de pacote para incluir o design principal
do microsoft dot entity
framework. E estou apenas configurando
a versão que
sei que estou usando
no projeto restante. Essa versão pode variar com o momento em que você está
fazendo o curso. Então, se você está seguindo esse
caminho, tudo bem. Caso contrário, você sempre pode
ir até New gate e adicionar o pacote de
design da estrutura de entidades como fizemos com todos
os outros pacotes. A próxima
etapa muito importante é
garantir que nosso projeto de
dados seja selecionado. Acabei de ver uma lista
para eliminar o ruído e os erros na seção, mas quero apenas
salientar que
precisamos que o projeto padrão aqui
seja qualquer projeto em que você
tenha o contexto de banco de dados, para nós, isso é dado. Vou selecionar os dados
e,
em seguida, pressionar o arco para
cima que me mostra o comando add migration initial
migration. Vá em frente e tente
novamente e, desta vez, criamos nossa migração. Agora, vamos dar uma
olhada no que temos aqui. Temos nossa pasta
chamada migrations, e ela tem pelo menos um arquivo com o nome da
migração que demos a ela Observe que há um
carimbo de data/hora nele. Também temos esse outro
que é o instantâneo do contexto. Então, basicamente,
neste momento, essa é a aparência do
banco de dados, e temos nosso arquivo de migração. Vamos dedicar algum tempo para avaliar exatamente o que
está em um arquivo de migração. Então, normalmente em SQL, você teria escrito instruções
SQL,
criado tabela, criado, bem,
desculpe, criado banco de dados e, em
seguida, criado tabela. Em seguida, você insere todos os
campos e as restrições. Se você estivesse escrevendo um roteiro. Se você estivesse usando o estúdio
de gerenciamento, estaria clicando e tudo isso teria sido
gerado em segundo plano. Bem, um arquivo
de migração praticamente será uma representação
de todas essas ações, mas com um contexto nítido em C e construído sobre o que
chamamos de padrão construtor, certo? Então, se você der uma
olhada,
parece complicado, mas se
sentar, respirar
fundo
e ver como desenvolvedor, e ver como desenvolvedor, você perceberá que
tudo o que está dizendo a você faz
sentido, certo? O construtor de migração, que é um objeto que está sendo passado
aqui, cria a tabela. Nome da mesa,
vazamentos, certo? E então, ele automaticamente garantirá
que ele crie. Então, embora
no contexto de DV, eu tenha sugerido, desculpe, estou apenas tentando
dizer muita coisa aqui Inicialmente, sugeri
que, ao
criarmos os modelos de classe, começássemos
com aqueles com menos dependência Porque se começássemos com uma
equipe e a equipe dependesse dessa propriedade de navegação, pois liga e liga
não existia, isso teria sido
um pequeno erro Portanto, teria sido prudente
da nossa parte criar uma liga. Então a liga já está lá quando estamos criando
coisas que precisam de liga. OK. Agora, no contexto do banco de dados, eu não necessariamente
segui essa ordem. Eu basicamente os listei
aleatoriamente. Então, eu não
os listei necessariamente na ordem em que queria que fossem criados
porque, obviamente, eu gostaria que as ligas
fossem criadas antes das equipes No entanto, se você observar
a migração, ela já passou
e viu que as ligas não
têm chaves estrangeiras, o Teams tem Portanto, as ligas precisam ser
criadas antes que as equipes o façam. Isso é basicamente o
que o FCR acabou de fazer. Então, está criando
a tabela classificativa. Está dando a ela o ID e o nome das
colunas. E se você olhar de perto
mais uma vez , seguindo as convenções de
nomes, ID
será automaticamente um int,
não anulável, e é
um incremento automático da identidade do servidor CQL Tudo isso foi gerado porque usamos a palavra ou
o ID do nome para essa coluna. FOR inferiu que isso é o que queríamos
como nossa chave primária E então você verá
aqui onde está dizendo que o tipo de coluna é string. Esse é um tipo C sharp, mas no banco de dados, estamos fazendo com que seja NTR Tudo bem? Apenas deixe
isso absorver um pouco Em seguida,
adicionamos as restrições que realmente tornam
essa a chave primária, que está na coluna ID Em seguida, ele repete essas ações. Construtor de migração,
crie tabelas , crie equipes, crie as
colunas, mais uma vez, inferindo qual é a chave
primária
e, em seguida, adicionando o ID
da liga como um int Mas depois vai um passo adiante com as
restrições em chave primária e
cria a chave estrangeira,
que está vinculando o ID da liga da
coluna às ligas
da tabela principal e ao
ID da coluna principal Então, você vê que tudo isso é inferido quando usamos nossas convenções de nomenclatura
adequadas Pode haver
momentos em que você precise, você sabe, sair do curso,
e isso é compreensível,
mas não deixe que seja
um caso em que você
sempre estará fazendo suas próprias coisas e lutando contra o QR,
e acabará fazendo o
dobro do trabalho quando o
QoR fica mais do que feliz em
fazer todo o trabalho por você QoR fica mais do que feliz em
fazer todo o trabalho Então, depois de criar tudo isso, ele segue em frente e cria um índice nessa coluna de chave
estrangeira. Agora você também
notará que
há dois. Desculpe, há dois métodos dentro
desse arquivo de migração. Estamos prontos e
acabamos, basicamente significa que quando estou atualizando o banco de dados ou
atualizando o banco de dados, é
isso que eu quero que seja feito D significa que, se eu quiser desfazer essa migração
do banco de dados, é
isso que deve ser feito D assim como up é o oposto de D, o código que está fará
algo totalmente contrário ao
código que está em do,
porque há momentos em que
você faz uma alteração no banco e então você diz: Oh, isso não é realmente o que eu queria fazer,
então você faz uma alteração. Mas quando você quer
fazer essa mudança, às vezes é mais fácil
falar do que fazer. Então, pelo menos, o FCR está dizendo, bem, estou dizendo ao banco de dados o
que fazer quando a
migração estiver sendo feita, e também vou
dizer o que não fazer ou o que fazer quando essa
migração estiver sendo desfeita Então, tudo isso é automatizado
dentro desse arquivo. OK. Tudo bem, agora
que temos a migração. Vamos terminar esta
lição executando o
comando mais mágico e provavelmente o mágico e provavelmente o
mais importante de todos, que é atualizar o banco de dados. Então, até agora, ainda
não temos nosso banco de dados. Vamos em frente e digitamos o banco de dados de hífen de
atualização. Pressione Enter, deixe-o construir. E o que esse comando
faz é examinar as migrações que
ele provavelmente
conhece e, em seguida, examinar as migrações que
não conhece, e então simplesmente
retoma a partir desse ponto
e executa as Aqui você vê que diz
aplicar a migração
e, em seguida, está
me dizendo qual migração foi aplicada, se houvesse cinco,
teria aplicado cinco, mas há apenas uma,
então está me
informando que foi feita
com sucesso. Então, quando eu olhar para trás
na minha lista de banco de dados, agora
verei o banco de dados o nome que eu defini
nessa string de conexão, núcleo EF da liga de
futebol. Quando eu expandir as tabelas, vou ver o histórico de
migração do EF, que é basicamente uma
tabela no banco de dados, acompanhando a migração. Assim, você pode saber até qual
versão seu banco de dados está. Certo? E então você tem
ligas e nós temos equipes E se você olhar, você vê as chaves, OK, então essa é
a chave primária. E você vê aqui que o ID
da Liga é uma chave estrangeira. Tudo isso foi configurado no banco de dados para nós,
cortesia dessa migração Agora, na próxima
lição, veremos como
poderíamos programar como
poderíamos programar essa migração, porque
talvez você não queira necessariamente executar atualização do banco de dados e deixar
que o FCR tenha domínio completo sobre
tudo no Mas existe uma maneira de
gerarmos um script SCO com base
nessas instruções e você poder
executá-lo sozinho Então, quando
voltarmos, veremos isso.
7. Gere scripts de migração: Pessoal, bem-vindos de volta.
Então, nesta lição, falaremos sobre como criar
scripts para nossa migração Portanto, o estudo de caso sobre
por que você
deseja criar um script em vez
de, você sabe, gerar um
arquivo de migração e fazê-lo
a partir do gerenciador de pacotes
talvez seja apenas a separação
dos controles. Talvez haja um administrador
de banco de dados responsável pelas alterações no
banco de dados. Então, você, o desenvolvedor, não
estaria fazendo
essas alterações no banco de dados, mas você fez a migração em
relação ao seu local. Você precisa entregá-lo a ele para que ele possa fazer isso
no meio ambiente. Você sabe, existem situações
diferentes que podem determinar se você pode ou não fazer isso da maneira que acabamos de fazer no vídeo anterior. Ou você teria que programar a migração e entregá-la. No entanto,
aprenderemos como criar um script para
a migração, e é um procedimento muito
simples Portanto, temos apenas uma migração, então o script não será
o mais complicado. Conforme o script cresce, há comportamentos
específicos que
são adicionados adequadamente, e o script cresce com as diferentes migrações, certo? Então, mais tarde, podemos revisitar
isso, mas agora, só
queremos ver como
programaríamos essa migração Então, no
console do gerenciador de pacotes, é bem simples. Você acabou de dizer migração de
hífen do script. O que ele fará
é a compilação normal
e, em seguida, gerará o arquivo SQL que corresponde
a todos esses comandos. Lá vamos nós. Você
verá aqui que ele está verificando se a tabela do
histórico de migração é nula e, em
seguida, crie essa tabela Em seguida, iniciamos a transação e criamos as
tabelas de acordo. Pegamos o índice, inserimos no histórico de
migração, a migração que acabou ser
executada, certo? É isso mesmo. Então, mais uma vez, isso provavelmente será
feito quando você quiser transferir a responsabilidade pelas alterações do banco de dados
ou pela criação
do banco de dados, seja o que for, para outra pessoa da sua equipe
na organização, e é isso que o FCO permite
8. Engineer de engenharia reversa: Ei, pessoal, bem-vindos de volta.
Então, nesta lição, veremos como podemos fazer engenharia
reversa de um
banco de dados que existe. Então, mais uma vez, primeiro temos o
código em que
podemos escrever o código que
gera o banco de dados. Mas em algumas situações, talvez
você já
tenha um banco de dados que deseja incluir em seus modelos de classe como o que temos
feito até Então, nesta lição, veremos isso,
e você
deve ter notado que eu já
criei um novo projeto. Portanto, você pode fazer isso se
quiser acompanhar, mas não é absolutamente
necessário, porque vamos apenas
examinar o comando e ver exatamente o que ele faz. Então, eu criei esse
novo projeto de console, que tem o único
propósito de estruturar o banco de dados, para você
possa ver
exatamente o que acontece Então, vou fazer disso
meu projeto inicial
e vamos
até o gerenciador de pacotes. E, para relembrar, vou pedir ajuda e vamos dar uma olhada no comando
para estruturar
o banco de dados Então, aqui está a lista
dos comandos, e vemos aqui que podemos
dizer scaffold DB context Então é a isso que
vamos prestar atenção nesta lição. Então, quando quisermos criar um andaime, vou copiá-lo e
colá-lo como o próximo
comando que vou executar,
e vamos usar o
mesmo banco de dados em que estamos
trabalhando em
todo o curso,
que é o banco trabalhando em
todo o curso, de dados da nossa
liga de futebol Vou
colocá-lo nos modelos, certo? Portanto, preciso especificar
o provedor. Então, fornecedor de hífen. Então isso é um parâmetro. Provedor, e nosso
provedor será microsoft dot tit framework
core dot SQL server Tudo bem? Então esse é o nome
do nosso pacote, e esse é o nosso provedor. Então, isso só mostra que esse
comando scaffold DB context pode ser usado para outros bancos de dados que
não são necessariamente SQL Server Tudo bem. Então,
especificamos o provedor e, em seguida, teremos que fornecer
a ele a conexão, toda a conexão,
aqui seria a mesma conexão
que estamos
usando basicamente em nosso contexto B. Então você só precisa formular
uma cadeia de conexão. Como eu já tenho um, não vou
digitá-lo do zero. Vou copiá-lo
porque, como eu disse, estamos usando o mesmo banco de dados. Mas seja qual for o banco de dados, você escreve uma string de conexão. fonte de dados é igual
ao servidor, está no catálogo inicial é igual ao nome
do banco de dados, porque pode estar em um
servidor em outro lugar. Pode não
estar necessariamente no mesmo servidor. Então, você só quer observar o fato
de escrever
essa string de conexão de acordo com a localização do banco de dados. Então, vou abrir
aspas e colocar minha string de conexão Feche as aspas. Então, mais uma coisa
que queremos fazer antes de tentar
executar esse comando. Queremos ter certeza de
que nosso projeto faça referência às mesmas
bibliotecas que tivemos que configurar quando estávamos fazendo nosso andaime inicial ou nossas migrações
iniciais Então, se
analisarmos os dados, veremos que precisávamos
referenciar o servidor de eliminação e
o design de referências de ferramentas e ferramentas. Tudo isso é
necessário. Vou pegar
todo esse grupo de itens. Copie e, em seguida, vá para nosso novo projeto, cole
e faça uma construção rápida. E depois
que isso for bem-sucedido, voltaremos ao console
do gerenciador de pacotes. Vou apenas
verificar se o provedor está correto e se
a conexão está correta. Vou me certificar de
que o projeto padrão ou o projeto de destino seja o projeto para o qual queremos
fazer o andaime E então eu vou
pressionar enter. Tudo bem. E depois de pressionar Enter, o prédio
me
deu um aviso t e depois uma exceção muito mortal Agora, como
eu disse, não vou evitar erros
neste curso Acho que ver os erros e resolvê-los é muito importante. Portanto, esse erro está dizendo que um erro relacionado à rede ocorreu
um erro relacionado à rede ao
tentar se conectar ao servidor. Isso significa que algo está errado com minha string de conexão. E acho que sei o que é. É a barra dupla porque temos que usar
a barra dupla escrever a cadeia de conexão
no contexto literal aqui Mas, em vez
do gerenciador de pacotes, não
preciso dessa barra dupla Vou removê-lo e depois vou tentar novamente. E desta vez, não tenho nenhum erro. Recebi o mesmo aviso,
mas não tenho nenhum erro. E se você der uma olhada por trás do
meu console de monitoramento de pacotes e dentro do projeto,
você verá vários arquivos
aparecendo. Tudo bem? Então, vamos dar uma olhada no que
cada um deles representa. Então, vou
derrubar qualquer coisa que não seja absolutamente necessária. E então vamos dar uma
olhada no contexto. Então, ele gerou um arquivo de contexto. O mesmo arquivo de contexto
que criamos manualmente, só para gerá-lo. Ele deu o nome
com base no banco de dados. Eu dei a ele a herança
do contexto de banco de dados, ele tem dois construtores,
um parâmetro s, um com o parâmetro aceitando opções de
algum outro aplicativo,
tudo Temos nossos conjuntos de banco de dados
criados como virtuais
e, em seguida, temos o mesmo método de
desconfiguração, certo Então, se eu fiz uma comparação
lado a lado, você meio que vê que, embora minha seja muito mais ou sempre
muito mais simplificada. É realmente a
mesma coisa, certo? Temos a desconfiguração
e, em seguida, ele diz que, se não houver
opções configuradas, ele insere essa
string de conexão exatamente como fizemos No entanto, ele
nos dá esse aviso, que é o mesmo
aviso que vimos no console do gerenciador de pacotes. Está apenas dizendo que você
deseja evitar colocar sua string de conexão diretamente dentro de um contexto como este. E, como eu disse,
estamos fazendo isso provisoriamente
porque é apenas um aplicativo de console, então estamos apenas colocando-o
ali apenas para fazê-lo funcionar Tudo bem. Mas em um aplicativo
maior, ele residiria em outro arquivo
e seria repassado sob demanda. Você também
anotará outro método, que ainda não
examinamos, mas, como eu disse,
você pode substituir a
maioria, se não todos, os métodos que vêm como padrão
da classe de contexto
do banco de dados, e esse outro método
está na criação de modelos Então, este está
basicamente dizendo que temos a anação
, a configuração de agrupamento relacional os conjuntos de caracteres que vamos usar
para esse banco de dados, e então diz equipe de
entidades de pontos do construtor de
modelos tem índice, tem uma liga
com muitas equipes
e tem
uma estrangeira, uma liga
com muitas equipes
e tem
uma lembre-se de que apenas seguindo quando estávamos criando
o banco de dados, isso meio que implicou tudo isso para nós ou fez
isso na migração Nessa situação, ele está examinando
um banco de dados existente
e, em seguida, está tentando
formular as regras para criar esse banco de dados existente
ou interagir com
ele que
precisam ser seguidas Tudo bem. Da mesma
forma, se mudássemos o nome desse banco e depois pedissemos
para você fazer uma migração, ele realmente
examinaria todas essas regras
para saber como fazer uma migração para um banco de dados totalmente
novo que pareça idêntico ao
que está estruturado Então, estou te dizendo FCR é muito, muito inteligente
e está fazendo muita coisa Está puxando muitas cordas
no fundo para você. Tudo bem, então é assim que o contexto
do banco de dados
realmente se parece. E então, se dermos uma olhada em nossas classes que foram geradas, você verá que obtemos
uma classe parcial, obtemos um conjunto de hash que representa
a coleção da equipe Então eu vou chegar a isso em um minuto. Mas obtemos essa construção e
obtemos as mesmas propriedades. E se estamos procurando uma equipe, parece praticamente
como fizemos a nossa. Então isso significa que estamos
no caminho certo, certo? Ainda temos essa chave
estrangeira e a propriedade de navegação
em direção à liga, que também é virtual Agora, voltando ao
que a classe da liga tem, vemos aqui que temos
uma propriedade adicional que não incluímos na nossa Então, vou mencionar
a liga original. Esse é o que
criamos, certo? E então aquele que estava andaime tem essa propriedade
adicional, que é uma coleção Agora, o conceito aqui
é que é demais. Nós sabemos disso. Nós o criamos e abordaremos muitos
mais tarde, mas eu só quero
destacar que o que ele está fazendo aqui é dizer que uma liga
terá acesso a várias equipes. Uma equipe, pertence a uma liga. Mas uma liga tem muitas equipes.
Esse é o único para muitos. Portanto, com essa
propriedade de navegação definida como uma coleção ou poderia
ter sido uma lista ou, bem, ela usou a coleção por padrão Quando estávamos criando,
poderíamos ter dito lista, poderíamos ter dito I numerable Mas a questão é que é a coleção de
itens relacionados a essa entidade. Então, apenas comprando uma liga, eu poderia incluir
todas as equipes, e isso me salvaria da dor de cabeça de ter que
fazer duas consultas separadas,
desculpe, para obter as equipes e a liga à qual
elas estão relacionadas Tudo bem, então é uma
coisa muito poderosa fazer isso assim. Então, mais tarde, podemos adicionar essa
propriedade de navegação à nossa, mas eu só
queria destacar o que exatamente estava sendo montado
e o que exatamente está e o que exatamente E basicamente isso é tudo para colocar
no banco de dados. Há outras pequenas coisas
que provavelmente você pode fazer, mas no nível mais básico, se houver um banco de dados, talvez tenha começado a
criar o servidor sc, ou se for parte de um projeto
legado ou de
um sistema legado e
você quiser reformulá-lo, basta começar a trabalhar nele sem começar
do zero Em seguida, você pode usar esse comando, trazer ou aquele banco de dados
na forma desses modelos. E então, por meio do contexto, você pode começar a trabalhar com ele desde o início. OK. OK.
9. Visualizar diagrama com ferramentas principais de Entity Framework: Ei, pessoal, bem-vindos de
volta nesta lição, vamos dar uma olhada nas ferramentas avançadas
do FCO
e como elas podem nos
ajudar a visualizar nosso
banco de dados por meio do Visual Studio Agora, isso vem logo depois
de eu mostrar
um diagrama de banco de dados
anterior, onde
estávamos no SQL Server Management
Studio, e eu gerei esse diagrama zero apenas para representar o banco de dados que estávamos
tentando criar na época Talvez você não
tenha necessariamente esse luxo,
e não estou dizendo que precisa comprar o estúdio de
gerenciamento,
mas usando as ferramentas elétricas da EFC por meio do Visual Studio, você pode gerar um diagrama
semelhante e ver como o
FCO visualiza seu banco de dados
ou qualquer banco de dados ao qual
ele esteja se conectando Então, vamos começar. Se você tem o Visual
Studio, isso é bom. Você simplesmente acessa extensões, você gerencia extensões. E quando esse diálogo surge, basta pesquisar as ferramentas elétricas do
FCO
e, quando você vê
nos resultados da pesquisa, basta clicar em
baixar Ok. Depois disso, precisaremos
reiniciar o Visual Studio, para que você possa prosseguir
e fazer isso rapidamente. Agora, depois de fechar o
Visual Studio, o gerenciador de extensões aparecerá e
concluirá a instalação. Se você ainda não tem esse recurso, o
editor DG ML instalado, que provavelmente foi instalado
com o Visual Studio, talvez você não precise
passar por essa etapa Mas se você estiver
passando pela etapa
, não há problema. Vá em frente e
clique em modificar para permitir que ele traga as dependências E uma vez concluído esse procedimento, você pode reabrir o Visual
Studio e, em seguida, o que vamos notar é que, quando
clicarmos com o botão direito do mouse em um projeto, veremos
um novo item de menu na forma de ferramentas poderosas de FQ Então, você verá
várias opções, algumas delas parecidas que discutimos
até agora
com as diferentes
migrações, andaimes e engenharia
avançada Todas essas coisas são
realmente possíveis por meio
dessas ferramentas poderosas de FQ sem a necessidade de escrever os comandos No entanto, para esta lição
em particular, quero me concentrar em
adicionar o diagrama de contexto. Então, é claro, mais uma vez, queremos ter certeza de que estamos em um projeto que tenha
o contexto de banco de dados. Vamos clicar com o botão direito do mouse,
acessar o FC Power Tools
e, em seguida, dizer Adicionar diagrama de contexto do
banco de dados. Em seguida, ele
gerará um novo arquivo com uma extensão dot dGML e
obteremos nosso diagrama Então, pensei que
seria capaz de selecionar, mas na verdade é só
arrastar por toda parte Então, veja aqui, ele está nos dando esse contexto de banco de dados na
forma de um diagrama, fornecendo a equipe, as
diferentes propriedades, e podemos clicar ou passar
o mouse sobre a propriedade para obter
mais informações sobre ela É a chave primária
e não é notável. Você vê todas essas
anotações ou todos os metadados estão disponíveis
aqui ao passar o mouse E se passarmos o mouse sobre a mesa, é praticamente a mesma coisa Então, do Visual Studio, podemos usar essa
ferramenta para visualizar exatamente o que está acontecendo em nosso banco de dados em um determinado ponto Agora, dado que
temos apenas duas tabelas certas. Agora, esse diagrama
pode não parecer tão empolgante quanto
provavelmente poderia ser. Mas você pode dedicar
algum tempo para dar uma olhada. Você pode segurar o
controle e rolar para ampliar um pouco ou pode
simplesmente alterar o
zoom aqui no topo e dar uma olhada na legenda onde
ela aponta quais são
os diferentes símbolos ou cores. Veja
aqui,
o vermelho representa
uma propriedade de navegação. O que é isso
roxo ou azulado, desculpe,
sou
um pouco daltônico,
mas essa cor púrpura
representa as chaves estrangeiras
e, em seguida, as
chaves primárias destacadas
e, em seguida, as diferentes
propriedades Então, você pode
dedicar algum tempo para simplesmente entender, absorver, ver os diferentes tipos
de relacionamentos. Mas à medida que nosso banco de dados cresce, revisaremos isso e veremos
como o FCR infere, quais tipos de relacionamentos e diferentes anotações
em propriedades diferentes à
medida que avançamos,
e então poderemos ver esse diagrama
evoluir e então poderemos ver esse diagrama revisaremos isso e veremos
como o FCR infere,
quais tipos de relacionamentos e
diferentes anotações
em propriedades diferentes à
medida que avançamos,
e então poderemos ver esse diagrama
evoluir com nosso banco de dados. Ok.
10. Como adicionar o registro de verbose à carga de trabalho do EF Core,: Ei, pessoal, bem-vindos
de volta. Portanto, neste menos, vamos
configurar o FCR com algumas opções adicionais para
fornecer mais detalhes
sobre o que ele está Então, o COR é, na verdade,
bastante normal, mas queríamos fazer barulho porque, quando estamos
executando nossos comandos, quero que tenhamos uma representação
visual do Q que está sendo orquestrado e das
diferentes operações sendo realizadas
em segundo plano enquanto fazemos Então, o que vamos fazer aqui é estender o
construtor de opções para saber que ele precisa se conectar E vou deixar que ele registre no console
a linha certa. Então, como estamos usando um
console instalado, ele está à direita. Então, registramos no console
a linha certa. E vou adicionar à
configuração ou, digamos, o pipeline do que
ele deveria estar registrando. Quero que ele registre o nome do
comando da categoria DB logger para que possamos ver uma
representação
do visor do que exatamente está sendo feito E vou
estender isso para que
saibam que queremos um nível de log. Eu ia dizer um nível de log. Informações sobre pontos. E acho que terei que
incluir que eles incluirão uma biblioteca para o registro de pontos de
extensões de pontos da Microsoft. Acho que acabei
de me adiantar. Portanto, é uma nova categoria de registrador de banco de dados
e, em seguida, fechamos uma chave
curva aqui. E então temos as informações do nível de
log, e então fechamos o
parêntese Então, dê uma olhada nessa
linha. Peça desculpas por isso Então, registramos na linha
direita do console, ponto direito, nova matriz
e, em seguida, passamos a
linha de nome do comando ali mesmo, comando do
banco de dados da categoria do registrador
DV, e
informamos que queremos um nível de registro de informações Então,
isso significa que tudo o que está fazendo,
queremos ver cuspido no console Outra coisa que
vou incluir é habilitar o registro de
dados confidenciais. Isso nos permite ver
ou diz ao FCR que
tudo o que está acontecendo em segundo plano e
que você provavelmente não
gostaria que seu usuário frontal
visse, nós queremos ver É nosso aplicativo que estamos aprendendo, então podemos pelo menos fazer
isso com risco zero, mas você não necessariamente
gostaria de fazer isso em um servidor de
produção, mas ele ajuda
na depuração em Então, agora que temos
tudo isso conectado, vou simplesmente
pular para o console Você não
precisa necessariamente fazer essa etapa. Eu meio que
escrevi um código para que possamos começar a
interagir com o curso F, para que você possa ver exatamente o que
tudo isso significaria Mas nos próximos vídeos, analisaremos
todo esse código juntos. Mas, por enquanto, eu só
quero que você veja uma amostra do registro
adicional. Então, na tela, você verá
o aplicativo do console. E se você olhar de perto, verá os troncos
sendo cuspidos. Portanto, temos informações
nesse carimbo de data/hora. Fizemos esse comando
e, em seguida, ele
mostra que
executamos um comando de banco de dados,
o parâmetro era. Então, o que aconteceria
naturalmente se
não ativássemos o registro
confidencial é que, nesses parâmetros, você não veria os valores. Então, habilitar o
registro confidencial, como eu disse, mostrará alguns detalhes que
teriam sido deixados de fora por, você sabe, motivos de segurança, daí o título
registro confidencial, certo? Assim, podemos ver exatamente quais
valores estão sendo passados, e o tamanho do valor, o tipo, o tempo limite do comando, e então vemos o SQL
real sendo gerado
inserido nessa tabela, os valores, e então ele está
apenas pegando esse parâmetro. Portanto, não está colocando
esse valor diretamente. Então, isso só mostra que
o FCR está ativamente fazendo a
parametrização, que é um componente essencial para a luta contra
a injeção de
SQL como uma brecha de segurança que muitas pessoas tentam Então, ele está parametrizando
a consulta simples
e, em seguida, seleciona
o ID a partir daí e atualiza a identidade do Mas, no momento,
não vou entrar em muitos detalhes sobre
o que o roteiro está fazendo. Eu só quero destacar
que agora estamos em uma posição em que, quando
vamos
escrever nossos comandos FC, podemos ver ativamente o SQL que está sendo
gerado em segundo plano. Também vemos o tempo
de execução de 61 milissegundos. Mas pode haver momentos talvez uma consulta esteja sendo executada por muito tempo e você esteja se
perguntando por que provavelmente
precisará ajustá-la Todas essas coisas que você pode
fazer quando tem esse tipo de registro
à sua disposição. Ok.
11. Operações simples de inserção: OK. Ei, pessoal, bem-vindos de volta. Então, nesta lição,
vamos
dar uma olhada em como podemos
realizar uma inserção simples e
selecionar a resolução usando o EF COR. Agora, saindo da
lição anterior, em que analisamos o registro detalhado e adicionamos
informações adicionais ao console Você deve ter visto que eu tinha
esse trecho de código
que devemos explorar e
tentar entender. Então, a primeira linha que eu
quero mostrar para você, e esta é mais uma vez,
o arquivo CS do programa dot em nosso aplicativo de console. Tudo bem. Então, a primeira linha que eu quero mostrar
para você é onde eu estou instanciando
nosso contexto de banco Portanto, eu tenho um contexto de banco de dados estático privado da liga de
futebol. E caso você esteja se perguntando de onde vem
esse nome,
esse é o nome do
nosso contexto de banco de dados aqui. Lembre-se de que eu
disse que esse arquivo representa a conexão com
o banco de dados. Ele tem a
cadeia de conexão e, bem
, conhece melhor
os elementos ou as entidades do banco de dados. Então, toda essa classe, à medida que nosso
banco de dados aumenta nossos contratos, essa classe é o
que nos dá esse acesso de gateway ao banco de dados e nos permite interagir com as
diferentes entidades. Então, temos que ter um
objeto instanciado dele. Agora, em um núcleo normal de pontos nic, bem, não vou dizer núcleo
normal de pontos nic. Em um aplicativo
principal maior, como
um aplicativo web ou até mesmo
um aplicativo blazer, você não veria isso
sendo feito dessa maneira Você o veria
sendo injetado. Mas, mais uma vez, estamos aqui para aprender sobre a
sintaxe do núcleo F. Portanto, estou tentando não me concentrar nesses outros aspectos do desenvolvimento neste curso em
particular. Tudo bem. Então, estamos instanciando nosso contexto de banco de dados da liga
de futebol. Estou chamando o contexto do objeto. Você teria visto
sugestões diferentes dadas a você, então você pode escolher a que
achar mais indicativa do que esse
objeto precisa representar Mas contexto é quase como
a palavra universal para significar o arquivo que
me conecta ao banco de dados, certo? Por isso, é usá-lo no nome
da classe e até mesmo
no nome do objeto. Mais uma vez, nomear
é mais subjetivo. Então, tudo bem se você
tiver outras ideias. Então, nós apenas instanciamos isso aqui. E então passamos para o principal. Assim como fizemos
na classe, isso é global para qualquer
outra função que vamos usar
dentro desse arquivo de classe. Agora, para adicionar algo
a uma tabela, a sintaxe seria contexto Mais uma vez, aquele objeto que representa uma conexão com
o banco de dados. Então, dizemos contexto, ponto. A tabela com
a qual esperamos interagir, e essa palavra ligas, está realmente relacionada ao que
chamamos de tabelas aqui Tudo bem? Então, isso são ligas Então, se eu redigitar
isso do zero, vou dizer contexto, ponto, quero ver
várias opções Eu posso adicionar, eu posso adicionar uma sincronização. Eu posso fazer várias coisas, mas então você verá as
diferentes propriedades, e algumas das propriedades
incluiriam os nomes das tabelas. Existem ligas e, se eu rolar um pouco
mais para baixo, há equipes Portanto, quantos conjuntos de bancos de dados
definimos no arquivo de contexto, podemos acessá-los
diretamente aqui sempre que
precisarmos interagir com essas tabelas. Então, contextualize as ligas e, em seguida, o que eu quero fazer
com a tabela classificativa Nessa situação,
eu quero acrescentar. Agora, se dermos uma
olhada na função de anúncio, você verá aqui que
a sobrecarga está esperando o poço,
não a disso
,
o parâmetro esperado pela Em vez disso
,
o parâmetro esperado pela função de anúncio
é do tipo liga, e está apenas dizendo que
espera uma entidade da liga. Então, em outras palavras, ele espera algum objeto do tipo liga. Então, essa é a beleza do F
Court que nos permite manter C nítido, porque na
sintaxe Q teríamos que
escrever algo como inserir em ligas, ,
teríamos que
escrever algo
como inserir em ligas, depois valores
e depois listar os valores, se não
formos especificar as colunas e depois os E sim, essa sintaxe
seria proposital, mas ter que colocá-la em C nítido e depois convertê-la
e fazer tudo isso, FC está apenas dizendo para
ficar em C nítido, eu tenho o Eu pego a tabela que você deseja adicionar
e, em seguida, você me dá os
dados que deseja adicionar. Então eu adicionei uma
liga de futebol da Jamaica aqui, mas então podemos mudar isso e vamos tentar a
Premier League inglesa Tudo bem. Então, uma nova Liga
instanciou um objeto, e estamos passando as propriedades,
e a Liga,
na verdade,
só tinha nomes de identificação Portanto, como o ID já é basicamente
um incremento, não
precisamos fornecer
um valor para o Com certeza, podemos acessá-lo, mas não precisamos fornecer um valor ao
adicionar. Tudo bem. Então, vamos seguir em frente e executar esse comando e
ver o que acontece. Os registros aqui
mostram que ele executou esse comando
com sucesso, levou 112 milissegundos e inseriu os
parâmetros e tudo E então aqui está a
sintaxe CQL que foi gerada. Então, insira em ligas, depois os nomes das colunas,
depois os valores
e, em seguida, o valor,
e então ele apenas atualizou esse objeto adequadamente Agora, outra linha que eu quero destacar é
a linha 14, que é a linha
definitiva para a qual você precisa ligar. Não importa o que você faça, pensando que está interagindo
com o banco de dados Depois de manipular dados, o que significa que você está adicionando atualizando ou excluindo dados, você precisa chamar alterações seguras pois todo esse método faz e outros métodos similares para
atualização e Tudo o que eles realmente fazem é rastrear as mudanças
que precisam acontecer, mas estão
rastreando-as na memória. Certo? Então,
enquanto o aplicativo estiver processando essa operação
específica, ele está apenas rastreando-a
na memória que, ok, eu sei que preciso adicionar isso.
Preciso atualizar isso. Preciso deletar isso.
Mas até que você salve as alterações, salve as alterações
, na verdade, gere o SQL, envie para o banco de dados
e tente fazer isso, e então
reverteremos se alguma coisa falhar e avisaremos o usuário
o que aconteceu. Tudo bem? Então é para isso
que servem as alterações salvas. E então chamamos
salvar as alterações de A sync, mas também há o salvamento das alterações sem
o AC, tudo bem. Vou usá-lo sem o AC pois essa não é uma função
assíncrona Vou manter as coisas simples. Mas quando estiver usando a programação
assíncrona, você sempre poderá usar a
versão A sync desses métodos Que, é claro, devem ser colocados em um método
assíncrono Então, eu simplesmente troquei todos os
meus métodos pelas versões de sincronização
A e mudei a
função principal para uma tarefa de sincronização A. E então, por causa disso, agora posso dizer que
um peso adiciona uma sincronização, peso, salvar alterações é uma sincronização. Agora, outra coisa, eu só quero explicar isso
um pouco mais. Porque aqui estou adicionando o objeto
diretamente no parâmetro. Isso nem
sempre é o caso,
porque, especialmente em aplicativos
maiores, como quando um usuário está
enviando o formulário e
, em um aplicativo da web,
ele envia o formulário, você obtém todos os
dados do formulário em um objeto que precisa
passar para o banco Você não necessariamente
gostaria de obtê-lo do formulário e
depois escrever uma nova liga e tentar colocar cada propriedade
com cada valor novamente. Então você sempre pode simplesmente inicializar Subq Sevar
League é igual a, e então eu posso inicializar
uma nova Deixe-me fazer isso para
reduzir qualquer digitação longa. Lá vamos nós. E então eu
posso dar essa liga. Você pode dizer que sou fã
de futebol, certo? Então, La Liga. Então essa
seria a liga espanhola. Agora que tenho meu objeto que representa a liga que
desejo adicionar ao banco de dados, agora
posso dizer adicionar AC e
passar esse objeto. Então, é realmente muito simples. Você pode criar seu objeto
em outro lugar, depois adicioná-lo
e, ao salvar as alterações, é quando ele é
confirmado no banco de dados. Agora, o que eu quero
ressaltar para você também é que, uma vez que
salvarmos as alterações, esse objeto será atualizado
automaticamente
com seu novo valor. Então, deixe-me adicionar um
ponto de interrupção e executar. E o que vou fazer aqui
é iniciar uma janela de observação e colocar o
objeto da liga lá para que possamos rastrear seus valores à medida que
avançamos linha por linha Tudo bem? Deixe-me fixar isso, torná-lo um pouco maior
para que possamos ver. Então, primeira linha, nada
aconteceu ainda. A liga é nula Então eu vou dar um passo.
E então você verá que g tem um ID de zero
e o valor Liga. Em seguida, ele salvará
as alterações
e, em seguida, avançaremos mais uma vez. E se você observar o objeto, verá que agora ele
tem o valor de ID. Então, isso é
útil quando você tem operações
encadeadas, certo Porque você pode ter
uma operação em que precisa adicionar algo
ao banco de dados
e, em seguida, precisa
desse valor, desse novo valor de ID para talvez exibir os detalhes desse
registro na próxima página. Então eu envio um formulário, você edita no banco de dados depois me leva à
página para ver os dados. Acabei de enviar o que está
lendo do banco de dados. Bem, é aqui
que isso é útil porque então eu posso
consultar o banco de dados diretamente nesse ID de registro logo após a conclusão da
operação Vou apenas pressionar F cinco para continuar com a execução. E mais uma vez, vemos nossa mensagem
muito amigável aqui dizendo que ela adicionou
esses dados ao banco de dados. Não, só por
uma questão de representação, como eu disse, queremos ver alguns dos
erros que podemos cometer O que vou
fazer é tentar adicionar um valor de ID a esse objeto antes que ele seja
adicionado ao banco de dados. Então eu sei que o ID
agora era sete. Então, eu vou colocar uma identificação. Realmente não importa qual valor, porque se
algo diferente de zero, quando for para
a operação de adição, ocorrerá um erro. Então, eu só
queria ver o tipo de feedback que vamos
receber da EFC, certo? Então, basta executá-lo e permitir
que ele faça o que precisa fazer. E então você vê
aqui que está falhando, e estamos recebendo
esse erro aqui Está dizendo que ocorreu um erro. exceção CQ não pode
inserir um valor explícito para a coluna de identidade quando a inserção de
identidade está ativada Então você vê que estamos
recebendo literalmente um desses erros que teríamos visto se
tentássemos fazer isso diretamente
no SQL. Se não for o mesmo erro, ele
será redigido de
forma muito semelhante a ele. Tudo bem. Então esse é o tipo
de feedback que EF COR nos dará
sempre que tentarmos isso. E veremos aqui no registro do
nosso console que
ele simplesmente falhou. Ele apenas diz que você falhou
e insere nisso, isso simplesmente falhou. Tudo bem? Então, se eu continuar, a execução terminará
adequadamente. Tudo bem. Então, estamos decidindo,
e eu só quero fazer mais
um exemplo de
como o trabalho da estrutura de entidades
pode facilitar a vida Então, nessa situação, eu quero adicionar uma nova liga, e estamos chamando
essa de Síria, essa é a liga italiana, e adicionamos a liga como
sabemos que temos que fazer, depois salvamos as alterações. Mas então eu preciso de informações desta liga para
conduzir outra operação. Nessa situação,
quero adicionar equipes. Então, obviamente, uma equipe
precisa existir em uma liga, certo? Então, eu preciso
das informações da liga que
acabou de ser criada
para criar essas equipes. Então, o que vou fazer é passar esse objeto
de liga para esse método. E então observe que
teremos que salvar as alterações
porque toda vez que estamos realizando alguma operação no contexto, precisamos salvar as alterações para que elas entrem em
vigor no banco de dados. Então, eu já
criei esse método ,
fiz uma tarefa AC estática e chamo isso de adicionar
equipes com ID da liga. Bem, eu ligo com o ID da liga. Deixe-me tirar a liga Deixe-me tirar o ID porque estou mostrando duas
operações diferentes neste exemplo, e você verá o porquê, e está usando um parâmetro
do tipo liga, que é a liga. Tudo bem. Então você pode simplesmente
ir em frente e replicar isso E então, nesse método, estou tentando algo diferente. Em vez de um
objeto a ser adicionado, estou fazendo uma lista de objetos
e, em seguida, vou adicionar um intervalo. Portanto, agora isso aproveitará
a capacidade
do FCR de
realizar operações em massa Agora, um pouco de
operações em massa, é um recurso
que permite ao FC agrupar várias operações, como
adicionar operações e assim por diante, em uma instrução Q
e disparar Mas então a equipe meio
que decidiu que, bem, seria mais eficiente,
com números menores de registros, fazer apenas instruções SQL
individuais. No entanto, em um determinado limite, você começará a ver uma
instrução SQL com todas
as informações Isso é apenas um
pouco sobre como essas operações em massa
funcionam em segundo plano. Mas nesse método, o que eu estou fazendo é
definir uma lista de equipes, e cada uma, eu estou
dando seu nome. Então, isso é ventilação, e esse ID da liga é o ID que vem do
nosso objeto da liga Certo? E então a
próxima equipe seria uma simulação seguindo o mesmo formato. Mas então o terceiro,
que é Aroma, eu estou fazendo algo diferente. Em vez de usar
a chave estrangeira, agora
estou usando o objeto de navegação
real e reutilizando o objeto
que foi passado Então, vamos ver
exatamente como isso funciona. Então, essa seria
a forma tradicional. Você tem a chave estrangeira,
insere o valor da chave estrangeira e ela está satisfeita, certo? Mas nessa equipe, vez de usar
a chave estrangeira, estou usando o
objeto real para passar. Então, vamos ver o que isso faria. Então, vou colocar um ponto de interrupção no
primeiro salvamento das alterações
e, em seguida, podemos
dar uma olhada e ver a operação passo a passo. Então, eu também adicionei o relógio
para as equipes, certo? Então, deixe-me dar uma olhada a liga ainda não
foi criada. Então, passo a passo, use F dez, para que eu não precise ir
ao contexto. Eu sei que temos nossa identificação de oito. Se olharmos em nosso objeto de liga, veremos que ele foi atualizado adequadamente. Em seguida, vou
usar o F 11 para entrar nesse método em que
as equipes agora estão definidas. Vou apenas
analisar sua criação. E então, se eu olhar
na lista de equipes, vejo que tenho todas elas
com seus respectivos IDs, e então Roma está aqui com o objeto de navegação
real em vez do ID da liga. Tudo bem? Portanto, o ID da liga da Roma é zero, mas o ID da liga para todos outros é oito, conforme o esperado. No entanto, a propriedade de navegação para todos os outros é nula
e, para Soma, ela tem sua propriedade de
navegação Agora, vamos ver o que acontece
depois de salvarmos as alterações. Vou
pressionar cinco para que
possamos ver os troncos
que são cuspidos. E você vê a primeira operação de
inserção acontecendo aqui mesmo
com a liga. Oh, não, isso. Este é com
a liga. Desculpe, certo? Então vemos outro
acontecendo para a primeira equipe, e vemos o ID, o ID da liga de oito
e o nome que está
sendo passado no nome do ID da liga, certo? E então, para a última, você percebe que é
a mesma instrução SQL. Ele pega o oito,
sabe que é Aroma e faz o mesmo
tipo de inserção. Então, isso só vai mostrar que
você pode inserir o valor real da chave estrangeira
e, é claro, ela fará o que precisa
fazer com a inserção,
ou você pode inserir todo o objeto e ele ainda
inferirá que, bem, o objeto tem sua chave primária Então, obviamente, esse
é um objeto relacionado, então a chave estrangeira seria o objeto de deslocamento da chave primária
e quaisquer outros dados Então, o FCR está fazendo isso por
você em segundo plano. Eu só queria destacar as diferentes maneiras de
inserir um registro que tem
uma dependência de chave estrangeira Agora, há algumas outras
coisas que você pode fazer, mas às vezes elas só
vêm com experiência, mas pelo menos se você
entender o básico de como adicionar algo
ao banco E observe que eu tinha que adicionar aqui, salvar as alterações e depois
adicionar novamente e salvar as alterações porque eu precisava que isso fosse adicionado para que a chave
fosse gerada para que eu pudesse realizar essa
operação. Tudo bem? outro lado, se eu tivesse feito algo assim e apenas
reservado um tempo para dar uma olhada Eu meio que o reformulei para não precisar sentar
e me ver digitar Mas o que estou fazendo ainda é
inicializar uma nova liga, e então eu tenho uma equipe.
Essa nova equipe tem o
nome Bern Munich, e então eu estou ultrapassando
este objetivo da liga Agora, observe que não estou
fazendo um Não estou salvando as alterações entre
essas duas linhas, certo? Então, primeira liga, equipe nova, e está conseguindo aquele
novo objetivo da liga. E então tudo o que estou fazendo é adicionar a equipe e salvar as alterações. E observe a diferença
entre esse anúncio e as linhas anteriores do ACC do anúncio Você tem a opção, é claro, destacar
a tabela com a qual
deseja interagir. Então, se eu dissesse que as ligas de
pontos de contexto adicionam uma sincronização e depois passam
um objeto de equipe, seria um erro
automático. Por quê? Porque, mais uma vez,
a operação de anúncios exige um tipo
de liga, certo? Então, eu não posso estar passando
um objeto de equipe. É claro que eu poderia ter dito que as equipes e tudo
ficariam bem. Mas então, se eu não
especificasse a tabela, estrutura de
entidades saberia
automaticamente que, ok, isso é um objeto de equipe ou é uma lista de objetos de equipe,
como fizemos aqui, onde eu acabei de dizer
contexto ponto adicionar intervalo passado na lista de equipe. Portanto, ele sabe que
, claramente, procurará
a tabela correspondente
para esse tipo de dados. Portanto, você não
precisa necessariamente , pelo menos ao lidar
com o contexto, não
precisa especificar a tabela o
tempo todo. Tudo bem. Mas o que eu quero
ressaltar é que quando eu faço isso e depois
salvo as alterações, ela realmente cria
a propriedade dependente e, em seguida, cria automaticamente a equipe com essa chave estrangeira. Então, vamos dar uma
olhada nessa operação. Então, quando você observar
o que ele gerou, verá que ele executou o comando para criar
a liga primeiro. Lá está criando
a Bundesliga, depois obtém esse ID
e, em seguida,
executa aquele que cria a equipe, passando
a chave estrangeira
para
a nova O SCEF CR está apenas puxando todas essas
cordas para você. Tudo porque eu disse,
quero uma nova equipe, e essa equipe faz parte de uma liga da qual eu não
sei a identidade. Foi o que disse, não tem
problema. Eu tenho isso. Ele segue em frente, cria
a liga, obtém o ID, cria a equipe e depois permite que você saiba que
tudo está pronto. Então, se você der uma
olhada nesse objeto de equipe, verá todos os dados relacionados
à equipe e à liga. Então, quando
voltarmos, começaremos a fazer algumas consultas selecionadas
porque, até agora, estávamos apenas inserindo dados, inserindo dados,
inserindo dados Agora, vamos ver como
podemos ler os dados
do banco de dados e exibi-los
em nosso aplicativo. OK.
12. Operações simples de seleção: Pessoal, nesta lição,
vamos falar sobre operações de seleção simples. Agora, antes de prosseguir, quero apenas
salientar que fizemos muitas coisas com
inserções simples e as extraí
em métodos individuais Então, eu me livrei do código e meio que
os comentei para que, quando
você olhasse para trás, pudesse ver o que está
acontecendo e onde. Tudo bem? Então, eu só peço que eles
comentem porque não queremos
continuar adicionando, adicionando e
adicionando os mesmos dados antigos. Então, agora é hora de analisarmos
a seleção, então vou separá-los,
colocá-los de lado
e, em seguida, podemos continuar a
contorná-los. Tudo bem. Então, quando falamos sobre seleção, esse seria o R no CRD. Então, eu não sei se eu uso essa sigla antes de
falar sobre esse assunto, mas CRD create read
update delete, Esse é um acrônimo amplamente usado no desenvolvimento de
banco de dados e representa basicamente
as quatro operações que você sempre executará em um
banco de dados em qualquer aplicativo Você está criando dados,
que é o que acabamos quando
analisamos a inserção, ou
seja, você
vai ler os dados, o que
significa que você deseja
recuperar os dados que
estão significa que você deseja no Isso é o que faremos agora
e, mais tarde,
veremos o U e o D, que significam
atualização e exclusão. Agora, quando queremos recuperar
dados do nosso banco de dados, começamos a pensar em
formular o que
chamamos de consultas de link
ou Link, que é a abreviação de consulta integrada de
linguagem. É basicamente um dialeto. Eu o chamo de dialeto de C sharp. É uma forma que permite escrever uma consulta usando C sharp
e, é claro, o FC traduzirá isso em QL. Vamos começar. A primeira e mais simples
coisa que você pode fazer. A consulta de link mais simples
para recuperar dados
do banco de dados seria e eu vou
definir apenas uma variável Então, eu quero que todas as
ligas voltem, e vou dizer que a Regus
é igual ao contexto,
que é a conexão com a tabela
do banco de dados na qual estou
interessado, que é E isso mostra
essa aparência no conjunto de ligas do
banco de Mas então eu quero isso em uma lista. Então, vou dizer ponto para listar. Em seguida, pedirá que eu
inclua uma certa biblioteca. Eu só vou controlar se você
vê que está me
dizendo que eu preciso do
link de pontos do sistema de bibliotecas para fazer isso. Vou seguir
em frente e incluir isso, esse erro desaparece. E assim,
eu já disse,
selecione uma estrela da
tabela chamada Ligas É basicamente isso. Certo? Então, o que vai
acontecer é que o contexto cria uma conexão com
o banco de dados. Ele vai para a
tabela classificativa e, em seguida ,
essa lista diz:
extraia os dados, traga-os de volta na forma de tula, mas depois materialize-os em
uma lista de objetos da liga Da mesma forma que
criamos a lista de equipes, onde está, aqui está
minha lista de equipes. Da mesma forma que criamos
a lista de equipes, é da mesma forma que ela se
materializará na
lista de ligas para Então, o que vou
fazer é fazer um para cada um, e vou dizer para
cada liga em ligas Eu quero consolar a linha direita do
ponto. Então, eu sou apenas um hífen
usando um hífen para separar o ID do Tudo bem. Então, vamos dar
uma olhada nisso. Tudo bem. E quando olhamos a saída, vemos aqui a instrução
que foi executada, selecionamos ID e nome das
ligas como L, certo? Então, isso é basicamente
aquela instrução SQL, que você pode simplesmente
copiar do console, ir para o seu
estúdio de gerenciamento e executar. Então, isso é muito útil quando você está
solucionando problemas, talvez você tenha escrito uma
consulta e
não esteja recebendo os
resultados desejados Você sempre pode obter
essa instrução SQL e tentar decifrar por que essa
pista está sendo malformada Mais uma vez, essa é uma ferramenta
muito poderosa. No entanto, quando
examinamos os objetos que
estão sendo impressos, vemos tudo o que
está no banco de dados. Então, durante o teste, provavelmente
entramos na Earth Strap
Premier League algumas, muitas vezes, também
na Premier League, mas também vemos todas as
outras ligas Então é isso que
obtemos quando simplesmente dizemos contexto, nome da
tabela e os fornecemos
como uma lista. Agora, algumas coisas importantes a serem observadas quando se
trata da sintaxe, isso é o que chamamos de instrução de
execução. Então, sem isso, essa
consulta não seria executada. Isso diria apenas: Bem, pernas agora é apenas o conjunto de hash ou
o conjunto de bancos de dados da mesa
chamado pernas, certo? Então, quando colocamos a lista “para”, é quando na verdade diz:
“Vou executar
essa consulta, enumerá-las e enviá-las de volta Então, se devêssemos
fazer algo como deixar de fora da lista de
tarefas e ainda executar isso. Essa consulta
não seria executada até que ela realmente iniciasse
os quatro ciclos de cada. Então, seria como se estivesse
em um estado de estase aqui. E então, quando começamos com quatro de cada vez,
ele dizia:
Ok, ok, deixe-me ir buscá-los para que eu possa
enumerar Agora, o perigo de fazer
isso dessa maneira é que a conexão permaneça aberta durante
esses quatro ciclos de cada. Agora, com apenas 15 discos, isso não parece
grande coisa. Quero dizer, ok, tudo bem.
Mas quando você está acessando
um banco de dados maior, você tem essa conexão aberta. E vamos pensar
em cada conexão com
o banco de dados como uma
operação cara em qualquer sistema, certo? Então, você quer reduzir
isso o máximo possível. E você também não
quer que uma conexão
fique aberta por muito tempo ou por
mais tempo do que o necessário. Então, quando fazemos uma
declaração como essa podemos até mesmo nos
livrar dessa liga,
parte dela e dizer apenas para
cada liga de realidade virtual em ligas parte dela e dizer apenas para
cada liga de contextuais A questão é que isso,
na verdade, criaria uma fechadura, e ainda por
cima muito ineficiente Na verdade,
quanto mais operações você realiza para alcançar cada item, o tempo entre
examinar cada item aumenta
e, é claro, a conexão permanece aberta e fica ainda
mais cara. Então, estou apenas apontando
que, sim, você pode tentar isso e funcionar, mas não é a maneira mais
eficiente de fazer isso. A maneira mais eficiente e inteligente de
fazer isso, mais uma vez, seria colocar essa operação em
execução, deixá-la iterar
e obter a lista,
e então essa lista não será armazenada Essa conexão não está
próxima do banco de dados
e, em seguida, você pode realizar todas as
suas operações e manipulações com os
dados posteriormente. Tudo bem. Então, isso é realmente tudo para fazer
as consultas de seleção simples. Eu meio que extraí todo esse código e o
coloquei nesse método, que é um método vazio estático Portanto, este não usa nenhuma operação
assíncrona. Portanto, não precisamos
torná-la uma tarefa assíncrona, certo? Portanto, é um vazio simples. E o que eu fiz foi
destacar qual é bom e
qual é muito ruim. Portanto, nem tudo que
funciona, mesmo
que
funcione, tem algumas
ramificações subjacentes das quais você pode não estar ciente, mas é por isso que estou aqui
para apontar qual é a melhor maneira de
devorar suas operações. OK.
13. Registros de filtragem: Ei, pessoal, bem-vindos de
volta a esta lição, começaremos a ver como
podemos filtrar nossas consultas. Agora, o estudo de caso da
filtragem é óbvio, certo? O que observamos
na seleção simples é que estamos selecionando tudo e, em seguida,
iterando tudo Há
situações em que você não quer tudo, você quer registros específicos, e é isso
que veremos primeiro. Então, eu criei um
método de filtros de consulta. E antes de prosseguir, quero destacar que
eu disse que anulamos isso porque nada síncrono estava acontecendo
nesse método Bem, graças à entidade
Framework Core, temos que listar A sync. E quando eu controlo isso, eu só tenho que adicionar isso usando a declaração para a entidade
Framework Core. E então, graças a isso, agora
posso fazer isso síncrono Além de adicionar o peso
antes da chamada AC. Então, vamos passar para
nossos filtros de consulta. Então, quando quisermos
adicionar um filtro de consulta, e eu vou dizer que ligas
são iguais ao nosso contexto, ponto, a tabela
em que estamos interessados, que é ligas, depois ponto, e eu tenho acesso
a vários métodos neste
lado Então, se eu quisesse dizer, me
dê todas as ligas o nome é igual a algum valor, então eu posso dizer ponto, onde e então essa função
onde recebe um parâmetro que se
parece com um predicado
ou é um predicado ou uma expressão Lambda Portanto, o formato de uma expressão Lambda é
que você tem algum token Vou
chamá-lo de Q. Na maioria dos exemplos na Internet,
você verá que eles usam Q. No entanto, não há nenhuma estipulação o que esse
token deve ser Claro, você o trata
como um nome de variável. Então, se você quiser usar Q, se quiser usar a liga, você sabe, seja o que for. Então, se eu dissesse Q e ela fosse
seguida por
essa seta Lambda, agora posso usar Q para representar qualquer
registro na tabela Então esse é o formato
da expressão Lambda. Se eu usasse x é a mesma coisa. Se eu escrevesse a
palavra liga, estou apenas destacando
que realmente não
importa como você a chama, todas funcionarão da
mesma maneira Talvez este leia melhor
porque, mais uma vez, está dizendo banco de dados, me
dê a tabela de chamadas de ligas e me dê os registros em qualquer liga tem que
qualquer liga tem
um nome equivalente
a algum valor Se quiséssemos encontrar, digamos
, a Siri, seria assim Mais uma vez, esse token
poderia ter sido Q, poderia ter sido x, poderia ter sido y,
poderia ter sido Z. Então, realmente não importa
o que você usa como esse token Agora, se eu fizer isso, ele não será executado até que, mais
uma vez, terminemos
com nossa lista. Como temos a
versão A sync da lista A, podemos dizer para listar A sync
e, em seguida, vou
aguardar isso e, claro, transformar o método em uma tarefa de sincronização A. Depois de fazer tudo isso, vou repetir essa operação em
que vou
imprimi-los todos no console. Aguardo essa
chamada de função e, claro, e espero ir antes de
tudo. Eu só vou consertar essas
coisas antes de seguir em frente. Então, quando ligarmos para
isso, vamos dar uma olhada
na tabela onde essa
condição é atendida. Então, isso vai
ser verdadeiro ou falso, então está cumprindo
a condição ou não. Se tiver atendido à condição, será adicionado à lista e, eventualmente, retornará aqui. Então, vamos executar essa consulta
e ver o que obtemos, certo? E então vemos que
está voltando. Temos nosso único
disco voltando. Se dermos uma boa
olhada no SQ, veremos que é apenas uma
simples consulta de seleção, mas adiciona essa cláusula were com essa condição. Tudo bem. Agora, eu programei. Observe que, diferentemente
das outras vezes em que você viu os parâmetros, na verdade,
ele apenas colocou o valor real
dentro da consulta, porque
estava meio codificado Então eu mencionei que a
parametrização é boa proteção
contra a injeção de CQL Portanto, o motivo pelo qual o FCR não usou parametrização
nessa situação é que ele vê que fui eu
quem codificou o
valor do Então, eu não colocaria uma injeção de SQL
diretamente no meu próprio código. Então, é claro, ok, é seguro porque foi meu mestre quem fez isso, então deve estar tudo bem, certo? Mas a realidade é
que, em situações normais, você provavelmente estaria obtendo
o que está procurando
em outro lugar, certo? Então, vamos ser um
pouco criativos aqui. Então, vou ajustar um pouco
essa função e vou dizer console
com o correto
da interliga Então, estou solicitando
ao usuário desta vez. Então, mais uma vez, este
é um aplicativo de console , mas em um
aplicativo da web ou assim por diante. Normalmente, você permite que o usuário descreva ou determine o
que ele precisa, certo? E você realiza a
filtragem de acordo. Então, estou solicitando ao usuário
e, em seguida, armazenaremos
a resposta nessa variável E então essa é a
variável que vou usar
para executar a consulta. Então, vou dizer onde a expressão
Lambda, ponto
Q é equivalente
ao nome da liga. Tudo bem? Também poderíamos até
dizer ponto igual, porque poderíamos confiar apenas nas funções C sharp que provavelmente usaríamos
em uma declaração normal, mas você percebe que isso se
parece com uma declaração, certo É o mesmo tipo
de operador lógico que você usaria
em uma condição. Porque, mais uma vez, essa é apenas uma condição que
precisa ser verdadeira ou, bem, precisa ser verdadeira
para ser incluída na lista. Certo? Então, agora nós
meio que nos gabamos disso. Agora podemos interagir um pouco mais
com ele. Então, eu vou executar isso e vamos
ver as instruções. Eu já entrei
na Síria, pressiono Enter. E então demorou 83 milissegundos para sair e dar uma olhada,
agora ele parametrizou E então ele está sendo executado
com o parâmetro. Então, veja, mais uma vez,
isso é automaticamente uma espécie de proteção contra injeção de
CQL por meio
da parametrização.
Estamos recuperando Estamos Agora, só temos uma
liga com esse nome, mas tínhamos várias ligas principais com listras
vermelhas Então, vou tentar isso
novamente com algo que eu sei que
retornará vários registros. Estamos tentando novamente com a Premier League com faixa
vermelha, e a filtragem agora
trará de volta todos os recordes Você vê que está funcionando. Está trazendo de volta
cada um que tem esse nome exato. E lembre-se de que desta vez
não usamos o
duplo sinal de igual. Usamos o C sharp
porque é uma string, então dissemos que ponto é
igual ao nome da liga. Portanto, ele nos permite escrever
a sintaxe C nítida com a qual
estamos familiarizados
em outras partes do nosso código diretamente na consulta, e ela trata
de todo o resto para nós Agora, vamos fazer
mais um experimento aqui. Há
situações em que seu filtro pode não ser tão exato quanto
verdadeiro ou falso. Pode ser uma espécie de lógica
difusa em que você quer
saber se ela contém, especialmente quando estamos
lidando com palavras, Então, em uma pesquisa típica, você seria capaz de
digitar uma parte
da palavra ou parte da
expressão que você está procurando, e então você
veria resultados correspondentes. Então, eu estendi a solicitação para dizer o
nome da interliga ou parte dela
e, em seguida, o que vamos
fazer é fazer duas consultas Então, vou pegar tudo
isso e duplicar
. E o que vou fazer é chamar uma de correspondências exatas
e a outra de correspondências parciais Então, para as correspondências parciais, não
vou dizer que ponto é igual, mas vou
dizer que ponto contém Porque em C sharp, se tentássemos
descobrir se uma string tem outra string para dizer
que o ponto contém. Então é isso que eu vou ignorar nesta
expressão. Então, vamos dar uma olhada nisso. Então, vou
usar “Vou inserir um bit de string” para pesquisar. Eu vou entrar na
Premier, certo? Eu sei que não tenho nenhuma liga que seja
compatível com a Premier. Então, já vimos as combinações
exatas funcionarem. Mas eu vou apenas
digitar a estreia. E então, o que você notará é que ele executará
as duas consultas. Então, vai
dizer que, executou
isso, está procurando um primeiro-ministro. Portanto, este tem a cláusula de desgaste para o nome premier da liga.
Claro, não há. Mas então este
tem o nome da liga como ou índice do gráfico. O
nome do ponto L é maior que zero. Então, basta traçar uma consulta
muito boa para dizer: estou procurando algo parecido o que está no
parâmetro. Tudo bem? E é aí que vemos
todas as nossas ligas que têm a palavra premier
voltando. Tudo bem. Então, essa é outra maneira filtrar
suas consultas Agora, quando se trata do,
você pode usar o conteúdo,
desculpe, ou você pode
usar as funções EF. Então, vou
duplicar isso e elogiar essa parte,
então essa é a primeira opção Outra opção seria
usar a função. Então, eu ainda preciso do token, ainda preciso inicializar isso, mas vou
dizer funções EF Ponto. E então você vê aqui, eu posso fazer contains, eu posso fazer e várias
outras funções que
estariam disponíveis para mim se eu
estivesse fazendo SQL direto. Alguns deles estão
aqui para serem acessados por nós. Então, eu vou fazer o
mesmo porque é mais
parecido com o que estamos procurando. Eu vou dizer tipo e depois vou
dizer o nome de um ponto. Então, o método usa, qual é a expressão
ou o que é a string? Qual é a coluna do banco de dados com a
qual estou comparando. E então o segundo parâmetro seria o padrão de string. Se eu quisesse colocar
um padrão específico, se você estiver familiarizado
com a cor, então você sabe que quando
você está lidando com algo parecido, você tem aquele curinga Então, eu poderia dizer módulo premier, o que significa que começa
com a palavra estreia Se colocarmos o módulo na frente, ele terminará com a palavra premier Então, o que quer que você
tenha feito em SQL para aquele módulo para
aquele bit curinga, você pode fazer isso dentro
da string e ela simplesmente a
agregará e criará essa expressão exatamente
como esperaríamos Então, em nossa situação, porque estamos lidando
com essa variável, eu tenho que ser um pouco mais sofisticado Não quero codificar
o que estamos procurando. Vou usar um
pouco de interpolação aqui e vou inserir o valor que vem
da entrada Então, estamos dizendo, me dê
todas as ligas em que o nome seja como esse padrão de
pesquisa. Tudo bem. Então, deixe-me fazer isso mais uma vez para que possamos ver o
que isso vai causar Desta vez, vou
digitar La. Eu não sei Eu
não tenho uma Liga. Não sei qual
outra liga no banco de dados pode ter
as letras LA nela, mas vemos a La Liga
sendo devolvida. E se olharmos para essa
consulta mais uma vez, vemos que ela está nos dando o formato e, em seguida, está
dizendo onde está o nome. Esse parâmetro. Então, você vê
que parece um pouco mais
limpo do que o que a consulta
contains gerou, mas,
no final das contas ambas nos
darão resultados muito semelhantes, se não os mesmos. Então, isso é tudo para uma
pequena experiência com a filtragem de nossas consultas Quando
voltarmos, veremos como
podemos agregar
dados, talvez um, o primeiro e a lista,
o último e a lista, a soma de tudo
na lista, esse tipo de coisa Então, quando
voltarmos, daremos uma olhada nisso.
14. Métodos de execução adicionais: Ei, pessoal, bem-vindos de volta.
Portanto, o objetivo desta lição é
entender ou apreciar alguns dos outros métodos que
temos disponíveis por meio
do Lincoln FCR e
como eles funcionam exatamente Então, eu já criei
um novo método, e isso é para métodos de
execução adicionais. Então, eu tenho uma declaração aqui que se parece com
uma instrução select proveniente de nossas atividades
anteriores onde temos um contexto
que leva para onde, e eu estou apenas dizendo que contém A. e eu estou apenas dizendo que contém A.
Agora, o estudo de caso de uma função
agregada ou de um desses métodos adicionais de
execução
seria que você provavelmente não
quer a lista inteira Provavelmente você quer que algo seja feito contra a lista ou
quer escolher a lista a dedo? Então, quando falamos sobre funções
agregadas em C, falamos sobre coisas
como Min max,
count, some, esses
tipos de operações, todas elas estão disponíveis para nós por meio dessas funções
agregadas adicionais Agora, outra coisa que
você provavelmente gostaria de
fazer é obter o primeiro ou
o último de uma lista, esse tipo de coisa, certo? Então, vou usar
isso como um exemplo rápido. E se eu quisesse a primeira liga com
a letra A no nome? Depois de ver toda essa declaração e
adicionar o filtro, eu a terminaria com
uma primeira ou padrão. Você verá aqui que
temos, é claro, os métodos assíncronos e, para cada AC, há
uma versão não AC Mas não é necessariamente
o contrário. Portanto, nem todo método tem
uma contraparte assíncrona, mas você verá isso OK. Então, aqui, posso dizer que quero um primeiro ou padrão ou
posso dizer o primeiro. A diferença entre
primeiro e primeiro ou padrão é que primeiro sempre
esperamos
ver uma lista e ela
receberá a primeira. Portanto, se nada for retornado, ele lançará uma exceção. Isso encerrará a execução
com um erro. Tudo bem? First ou default over dirá:
tentarei obter o primeiro
e, dirá:
tentarei obter o primeiro se não houver nada para obter, retornarei nulo sem encerrar a
execução nesse ponto Tudo bem, então primeiro ou padrão
é provavelmente uma parte mais segura. E então o que
isso fará é recuperar a única liga que está
no topo da lista. Tudo bem. Agora,
poderíamos realmente simplificar isso porque
o que estamos fazendo aqui é dizer me dê
a cláusula de trabalho e , em seguida, coloque a condição
e me dê a primeira Na verdade
, eu poderia ter feito isso. Eu poderia ter dito no contexto em que as ligas adotam a primeira estrela
como padrão, essa condição. Esse é um método de execução. Lembre-se de
voltar à nossa seleção simples. Sing context dot leg realmente
não faz nada, mas uma vez
que colocamos esse método, ele é executado. Vimos a mesma coisa com
a lista de itens e os produtos. Mas nessa situação,
posso simplesmente dizer primeira estrela padrão e
depois essa condição
e , em seguida, ele
executará a consulta de acordo. Então, vou dar uma olhada
e mostrar alguns outros métodos de execução comumente
usados. Então, vou
substituir essa linha uma declaração simples que está configurando nosso banco de dados aqui, certo? E, claro, a partir do
conjunto de banco de dados, podemos acessar os métodos de
execução. Então, vamos
examiná-los mais ou menos em ordem. Então, nós já
vimos a torrada. Sabemos que os
pedágios
executarão a declaração Selcti Também temos o primeiro
e o primeiro R padrão, e acabamos de discutir a diferença entre
os dois,
então podemos dizer que os vazamentos pontuam primeiro
uma sincronização ou o primeiro R padroniza
uma sincronização e, mais uma vez, eles têm
versões não assíncronas Com base na sua situação, você pode estar usando a sincronização A, pode não estar usando a sincronização A, mas vou apenas mantê-la consistente e continuar
com a sincronização A. Também temos o padrão único
ou único. Single, ele faz
o que o
primeiro faria, exceto que o primeiro é ver uma lista e
escolher o primeiro, literalmente o primeiro da lista. O Single operará de
forma semelhante à primeira em que, se estiver procurando por uma, primeira espera uma lista e ela
pega a primeira Se nenhuma lista for retornada
, isso gerará um erro Single espera que apenas
um registro seja retornado. Então, seja qual for o qu, você espera que apenas um
registro seja retornado Se ele ver mais de um, ele também lançará uma exceção. Single simplesmente não lançará a exceção, mas retornará o padrão em
circunstâncias semelhantes. Você sempre pode ler
mais ao passar mouse sobre o método, pois ele lhe dará alguma
instrução sobre o que ele faz Agora, quando se trata de algumas
das funções agregadas tradicionais que provavelmente
conheceríamos do
SQL, você vê count Assim, você pode dizer que a contagem de pontos da liga diminui, você executará
a consulta de contagem Você tem uma contagem longa,
você tem o mínimo, você tem o máximo, você tem S, você tem uma série de outras. Como eu disse, você
sempre pode dizer pontos da liga ou
ponto da tabela de pontos do contexto
e, em seguida,
percorrer e ver
a infinidade de métodos
disponíveis para você a infinidade de métodos
disponíveis Você pode optar por usá-los
quando precisar usá-los. Mas sentar e
tentar passar por todos eles ao mesmo tempo pode
ser cansativo, mas qualquer
momento
você acha que tem uma ideia em mente Você sempre pode simplesmente controlar
o
espaço de pontos e dar uma
olhada e ver de qual dessas carnes você precisa naquele
momento Agora, outro método de execução, que não é necessariamente um método de consulta
como um desses, mas que será executado em
um conjunto de banco de dados, é encontrar uma sincronização. Na verdade, este será encontrado com base em um valor, então esse valor
será o valor-chave, certo? Então, encontra uma entidade com
uma determinada chave primária. Então, quando você diz encontrar uma sincronização, espera-se que
você insira
qualquer identificador
exclusivo que seja, portanto, essa tabela
e, em qualquer identificador
exclusivo que seja, portanto, essa tabela
e, seguida, ela trará de
volta esse registro. Isso o trará de volta
ou trará de volta o nulo, certo? Ou retornará o
registro ou retornará nulo. Então é assim que o
find a sync funciona. Então, vamos tentar executar e ver exatamente como isso
funcionaria para nós Então, eu defini um ponto de interrupção
no início desse método e vou
passar passo a passo para que possamos ver a
quel C sendo gerada Acredito que quando chegar
ao único e único ou ao padrão ou pelo
menos ao primeiro, provavelmente gerará um
erro em um deles, mas vamos dar uma olhada e ver exatamente
o que está acontecendo. Então, coloquei minhas janelas
lado a lado para que
possamos ver cada passo do caminho. Então, quando dizemos para listar, vamos
executá-la, e então vemos aqui
que estamos recebendo
aquela consulta de seleção com a qual já estamos
familiarizados. Então, eu vou
fazer o primeiro. Então você vê que está
recebendo o primeiro, é selecionar o melhor. Da liga. Tudo bem. Então é isso que o primeiro faz. E o primeiro ou o padrão, se não me engano, geramos praticamente
o mesmo SQL do primeiro Mas, como eu disse, se primeiro
não ver nada, então ele lançará uma exceção. Agora, single definitivamente
lançará uma exceção porque
espera apenas um disco,
mas está pegando a lista
e dizendo um single Então, quando usamos essa, ela gera essa
exceção. Lá vamos nós. Então, a exceção é que sequência contém
mais de um elemento porque esperava que apenas um elemento
fosse retornado, certo? Então, vou
encerrar essa execução e vou comentar
sobre essa linha apenas para que
possamos continuar com o
resto da execução. Então eu continuei a execução contra todos os outros métodos, e você verá à direita, alguns deles foram
bem-sucedidos, outros não. Então, um único padrão singular e praticamente todos esses padrões
matemáticos por meio de erros, verdade, porque, bem, eu não estou realmente fazendo nada
matemático aqui. Eu tenho que ter certeza de que estou encontrando o
meio de algo, encontrando o máximo de algo. Obviamente, isso não está realmente acontecendo quando eu
digo ligas, certo? Mas a questão é que esses
são alguns métodos adicionais que você pode usar
ao realizar operações mais complexas. E se você olhar para a direita, verá que,
até o berço, quando
perguntamos quando pedimos contagem e
pedimos uma contagem longa, diferença entre
os dois era que
selecionávamos cont star para
o berço e, em seguida, selecionar cont big star
para o A única diferença material, na
verdade, é que a contagem retorna um número inteiro e essa
retorna um grande número inteiro Então, você sabe, com base
no tamanho do banco de dados, você pode nunca acabar usando contagem
longa ou grande em SQL, mas o método
existe de qualquer maneira. Então, isso é realmente tudo para
os métodos de execução. À medida que avançamos, podemos
encontrar utilidade para eles. E talvez precisemos interagir
com eles de outra forma. Mas, no momento, não temos. Vou comentar todos aqueles que
provavelmente apresentaram erros e só quero que vejamos o q que é gerado
quando tentamos encontrar. Então, vemos aqui que a
execução da descoberta é que ela encontra uma parte superior
onde essa condição é atendida. Então, tudo isso mais uma vez
é gerado para nós. E muito provavelmente não
vamos codificar esse ID de qualquer maneira,
esse ID estaria
vindo de algum lugar, você sabe, como quando alguém clica em
editar na sua interface de usuário Você precisa saber qual
registro eles pretendem editar. Você precisa
encontrar esse registro, devolvê-lo e
apresentá-lo ao usuário. Então, esse é um estudo de caso de
quando você usaria essa descoberta. Então, é isso para nós que
analisamos métodos de
execução adicionais. Como você viu, há
uma lista muito mais longa do que a que
examinamos aqui. Mas você tem essas
quatro referências e tenho certeza de que encontrará um bom
uso para elas no futuro.
15. Sintaxe alternativa LINQ: Ei, pessoal, bem-vindos
de volta. Nesta lição, examinaremos a sintaxe alternativa do link Então, até agora, analisamos
links na forma
desses métodos de execução e diferentes
expressões Lambda que
podemos colocar em alguns
deles para tornar
nossas operações
exclusivas de acordo com nossas necessidades Agora, tudo bem, usar o
método de expressão Lambda é perfeitamente adequado
e, como você pode ver,
ele pode ser escrito em uma linha, de forma agradável e limpa No entanto, há uma sintaxe
alternativa que alguns desenvolvedores
podem achar um pouco mais intuitiva porque se parece um pouco mais com o SQL
tradicional, mas ainda é C nítida Então, essa é, na verdade,
a primeira maneira que usei para
escrever um link antes de descobrir ou me familiarizar o suficiente com as expressões Lambda E eu tenho o código
preparado aqui para você, então vou apenas
orientá-lo. Então, desta vez, estamos
analisando as equipes, certo? E então nossa sintaxe aqui
está dizendo a partir de algum símbolo. Então, isso pode ser, você sabe, usamos Q em nossas expressões
Lambda Isso representa algo
parecido com esse Q. Poderíamos dizer equipe, poderíamos dizer Q. Estou dizendo I. Tudo Então,
de I em dizemos a tabela que estamos interessados
em examinar. Então,
contextualize essas equipes e selecione. Então, como eu disse, parece um
pouco mais com Q porque, na verdade, tem algumas dessas palavras-chave
SQL, certo? É um pouco
invertido porque teria sido uma estrela selecionada da tabela E este é do
registro na tabela, selecione o registro, ou poderíamos dizer que
selecione algo específico. Mas veremos isso mais tarde. Então, quando eu fizer essa consulta, ela me dará uma consulta
sobre equipes, certo? Então isso significa que eu preciso
converter isso em uma lista. Mas vamos executar
e ver o que obtemos, e então podemos refinar
à medida que avançamos Se você observar isso, ele realmente executou essa consulta
perfeitamente, certo? Ele nos deu nossa declaração
seleta e está
devolvendo nossas equipes. Portanto, não precisávamos
dizer explicitamente para listar e
tentar convertê-la Agora, um dos benefícios, no entanto, de tê-lo como uma lista, é que, quando está
na forma de quarable, nossa capacidade de manipulá-lo até certo ponto
é limitada, Então, se eu analisasse as equipes, há certas funções aqui que são exclusivas do
i quarable e há certas funções
que são exclusivas listas que você provavelmente
gostaria de usar mais tarde em sua codificação e que você realmente não conseguirá entender quando está lidando
com um i Então, de tempos em tempos, eu coloco
tudo isso entre parênteses
e digo para listar, e isso me
devolve minha lista, que é um pouco mais nativa
do que eu gostaria fazer no meu código C sharp
no final do Claro, para fazer isso, eu
tenho que mudar meu método de void para AC, certo? Então, estamos recebendo nossa lista
e, como você pode ver, a lista e os tipos de coleção funcionam forma
bastante semelhante,
mas, como eu disse, há certas coisas
que a lista
nos oferece que um enumerável consultável, e o outro tipo de coleções de
listas ou
tipos de coleções em C
sharp Mas é claro que a
situação de cada um é diferente. Use o que for
apropriado ao seu contexto. Agora, vamos estender isso. Também analisamos uma
consulta, ou desculpe. Também analisamos a
filtragem de nossas consultas. Então, agora, isso é apenas
fazer uma estrela de seleção padrão. Certo? Mas e se
quiséssemos uma cláusula de conscientização Bem, diríamos
de I na tabela, e eu vou
quebrar a linha aqui. Portanto, parece um pouco mais legível. Onde, e você
verá que isso meio destaca essas
palavras-chave para nós. Então, onde I
representa a expressão ou qualquer
registro no banco de dados. Assim, posso dizer onde meu
nome é equivalente e depois colocar meus registros. Então, da mesma forma
que fomos
capazes de injetar ou, você sabe, uma variável ou um nome estático
ou qualquer uma dessas coisas, podemos fazer tudo
isso aqui Deixe-me ver se isso
funcionaria. Vou tentar dizer onde eu nomeio ou deixe-me dizer
como funciona o EF. E então isso
seria “Eu não nomeio”. E então temos
o nome da liga, o qual vou fazer uma rápida solicitação desse
método,
pois também seria o nome da equipe Então, insira o nome da equipe. Deixe-me mudar o
nome do verbo. E lá vamos nós. Então, estamos solicitando o nome da
equipe e parte dela. E então estamos dizendo
da tabela da equipe onde o ponto funciona
como o nome do ponto, certo? Nossa expressão, e
então queremos selecionar, e então queremos colocar
tudo isso em uma lista para
retornar às nossas equipes de chamadas
variáveis. Então isso vai
funcionar, é claro. Estou apenas destacando
o fato de que podemos usar a sintaxe alternativa da mesma forma que
usamos nossa expressão Lambda Então, aqui estou testando
e digitando B A Y como parte do nome da equipe Vemos nossa instrução select com a declaração sendo
gerada para nós e estamos recuperando
Bar e Municx, pois é a única equipe que
temos que tem BAY nela Então, mais uma vez, essa é
nossa sintaxe alternativa. Tudo o que você pode fazer
na expressão Lambda, você também pode fazer
nesse tipo de sintaxe Pessoalmente, no entanto, acho que as expressões
Lambda são um pouco mais fáceis Então, desde que me senti
confortável com eles, deixei de escrever
minhas perguntas dessa forma não escrevo
perguntas como essa Para ser honesto, não escrevo
perguntas como essa
há anos, mas é bom ter
o conhecimento
de todas as suas opções
e alternativas, se necessário. OK.
16. Consulta de atualização simples: Ei, pessoal, bem-vindos de
volta nesta lição, vamos analisar como
realizar uma operação de atualização. Agora, o
fluxo de trabalho geral para uma atualização seria
recuperar o registro que pretende modificar
, fazer a modificação e salvar as alterações Então, esse é um fluxo de trabalho típico. Em qualquer aplicativo que você usa, é
isso que está acontecendo nos
bastidores. Você indica que
deseja editar o registro, ele encontra esse registro, o
apresenta a você, faz alterações
e, quando você
clica em Salvar, ele. Bem, você teria feito
as alterações no registro e, em seguida, o salvamento confirmaria essas
alterações no banco de dados. Tudo bem Então, vamos primeiro analisar a recuperação dos registros E se quiséssemos modificar? E temos alguns, deixe-me
dar uma olhada em nossas ligas. Temos alguns
valores duplicados aqui. Acho que temos três recordes da liga de futebol com
faixa vermelha. E sim, nós temos. Portanto, temos IDs ,
dois, três e quatro
sendo iguais. Então, o que vou
fazer é mudar os nomes
de alguns deles, certo? Então, vou mudar
o nome de três. É uma duplicata, mas, em
retrospectiva, percebemos
que realmente deveria ter
sido a premiership escocesa
, que realmente deveria ter sido a premiership escocesa Então, sabemos que queremos
modificar o registro com ID três. Então, o que vou fazer
para recuperar o registro é SVR League,
z igual ao contexto, as ligas encontram, e
eu vou usar apenas É claro que, se eu estiver usando uma sincronização, tenho que transformar meu
método em uma tarefa de sincronização e esperar aqui. Então, vamos
dizer, encontre uma sincronização
e, em seguida, lembre-se de
que tudo o que precisamos transmitir é a chave primária, então sabemos que queremos
gravar com o ID três. Agora, quando tivermos essa liga,
a mudança que eu quero
fazer é o nome do ponto da liga, quero que esse nome agora
seja premiereship escocês Em seguida, salvamos nossas alterações. Então, já analisamos as alterações
salvas de quando
inserimos as mesmas alterações salvas Sempre que você for
aumentar os dados no banco de dados, precisará chamar isso
para confirmar o comando Em seguida, quero imprimir o resultado disso ou
quero imprimir de volta
para a tela desse registro. Vou apenas criar um
método chamado get record, que serve especificamente
para encontrar esse registro. Eu tenho isso definido aqui no topo, ou eu vou dizer Varg, vá e encontre o mesmo disco Então, após salvar as alterações, ele teria fechado a
conexão com o banco de dados. Vou apenas
aguardar a obtenção do registro, que vai
recuperar o registro e depois imprimi-lo de volta na tela apenas para mostrar que
o procedimento de atualização
foi bem-sucedido Então, vamos dar a esse um objetivo. Então, quando eu executo, vemos aqui que ele
está fazendo a seleção, aí
que ele está
fazendo a busca, então ele recupera o registro
e, em seguida, está
realizando essa atualização, então ele retém a chave primária e o novo valor
para esse E então ele executa
essa instrução de atualização, define o nome para ser qualquer
valor nesse parâmetro, onde o ID está
nesse parâmetro, e então ele
prossegue e atualiza. E então, é claro,
nosso registro get está apenas reabrindo
aquela consulta de seleção, que é uma selquy, e
nos devolvendo esse registro. Tudo bem Então, vamos tentar isso de novo, e eu não vou
mudar nada. Vou deixar
o mesmo registro. Eu vou fazer
a mesma mudança e tudo vai
continuar o mesmo. E então vamos ver
o que aconteceu. Desta vez, não temos
uma declaração de atualização. Anote isso, certo? Não temos uma declaração de
atualização porque ela percebe que
qualquer mudança que eu esteja fazendo, não
é realmente uma mudança Esse já é o valor
no banco de dados. Então, não vai se preocupar em
perder tempo dizendo:
Oh, eu preciso fazer uma mudança CEFCO está escolhendo, de forma inteligente não abrir uma conexão com o banco de dados e executar um comando que ele percebe que não
é necessário Agora, o que permite que esse
tipo de mudança aconteça, significa que o FCR está vendo que os dados que estamos apresentando para esse campo são diferentes, então ele sabe como
salvar as alterações Isso se chama rastreamento, certo? Analisamos o rastreamento e
nenhum rastreamento posteriormente. Mas apenas como uma prévia rápida, sempre que
estamos modificando objetos, FCR está na verdade rastreando
na memória quais objetos ele tem, se houver
alguma alteração feita neles, de modo que, quando
dizemos salvar alterações, ele literalmente dirá: Ok, eu posso ver que uma alteração
foi feita aqui, eu tenho que confirmar essa alteração, etc Então é isso que o rastreamento nos
permite fazer. Agora, existem
outras maneiras de
realizar uma atualização, porque
uma atualização pode nunca ser tão
simples quanto encontrar esse valor exato
e apenas alterar
uma propriedade e depois
salvar Muitas vezes, quando as pessoas,
especialmente, têm interfaces de usuário e estão interagindo
com um formulário, quando permitimos que elas
editem os dados, não
sabemos o que mudou Então,
não podemos ter certeza de que, ok, vamos apenas atualizar o nome e apenas
atualizar isso e aquilo. Não sabemos se, talvez, ao editar uma equipe,
eles
mudem a
liga e o nome. Nós não sabemos. Então, para este outro exemplo,
vou usar a equipe. Então, renomeei nosso método de
atualização de registro para simples
atualização de registro da liga Portanto, está claro que
estamos lidando com a liga e
foi uma atualização simples, e agora temos uma atualização
simples do registro da equipe. Então, vamos dar uma
olhada na alternativa. Agora, no
caso de alguém usando uma interface web
ter enviado o formulário, isso significa que já temos todas as informações sobre o registro de que precisamos naquele
momento, significa que não precisamos
procurá-lo antes da atualização
porque já o encontramos antes de
mostrá-lo ao usuário. Agora que o usuário enviou, temos os novos dados. Tudo bem Então, vou simular isso criando um novo poço, um objeto do tipo equipe, certo? E então o que vou fazer
é especificar um ID desta vez. Então, até agora, não
demos nenhum ID a nenhum dos nossos objetos porque
eles são incrementados automaticamente No entanto, o que precisamos
perceber é que, quando
um ID está presente, é
claro que examinará
as tabelas
do banco de dados em busca
do registro com esse ID. Então, eu vou até
a mesa da equipe. E o que vou fazer é inserir
manualmente apenas para
que possamos passar por essa equipe de atividades
que é local. Está na Premier League da Red
Strip, mas vou colocá-lo com alguns erros de ortografia,
certo? É o Tivoli Este é o Tivoli, e vou colocá-lo com
o ID errado da liga, porque não está
na liga oito, e com base
nas equipes da liga oito, podemos supor Não é na Síria, então
temos que fazer esse tipo
de atualização, certo? Então, digamos que isso foi digitado
erroneamente
por algum usuário
e, em seguida, outro usuário
percebe esse erro
e está decidindo escrevê-lo de forma errada Então, eles teriam
recebido
o formulário e, em seguida,
fizeram as correções
e, em seguida,
enviaram o formulário Então, o objeto que eles
teriam enviado seria algo assim,
onde o ID é sete, ou
seja, o ID
dessa equipe, sim. E o nome que
foi corrigido é Tivoli Gardens FC com O em vez de AW, essa é
a grafia correta E então o ID da liga agora
seria a
Premier League Red Stripe, certo? Então, vamos usar o League ID two. Vemos que temos outra
duplicata, mas tudo bem. Vamos usar a
liga com ID dois. Portanto, essa é a atualização que
esse usuário está enviando. Agora, como colocamos esse novo
registro no banco de dados? Bem, podemos dizer contextualizar equipes da liga de
pontos. Estamos lidando com a atualização de pontos
das equipes. Portanto, temos um método de atualização
que, assim como o
anúncio, usa um objeto do tipo de dados que corresponde à tabela. Então, temos nosso objeto de equipe. Observo que não há versão assíncrona, não há uma versão
assíncrona Temos o single e a versão em lote, e já
analisamos o intervalo de lotes, o que significa que, se tivermos vários
deles para atualizar, acabamos de entregar a lista e ela lidará com
todos eles para nós. No momento, estamos apenas
vendo o single. E depois disso,
temos que chamar nosso contexto de dot-save changes. E usaremos a
sincronização A para isso. E, claro, eu
tenho que
sincronizar isso e então todos os nossos
problemas são resolvidos. Vamos dar uma olhada no que é feito quando aprovamos
esse tipo de atualização. Você verá que é um tipo
similar de operação. Ninguém, ele não é atualizado
novamente porque vê o ID. Portanto, ele sabe que há
uma equipe com ID sete
e, em seguida, a
encontrará automaticamente. Bem, não precisa encontrá-la
porque a declaração de atualização diz mudança de ID da liga, mudança de
nome em que
o ID é equivalente ao ID que viu
entrar no registro. Então, ele está fazendo tudo isso automaticamente quando o ID do
registro está lá. Então, vamos analisar
várias permutações. Se não especificássemos esse ID, o que realmente aconteceria? E eu vou usar
outro time de futebol, vamos o Ciba United, que também está na Premier League de faixa
vermelha Então, vamos tentar esse
e observar a diferença. Isso não tinha identificação. Tiramos a identidade e foi usada como uma fila para fazer uma inserção. Tome nota disso. Então, o comando atualização
ou a função de atualização
estava dizendo que, eu não vejo uma chave
primária
nisso, isso claramente não existe
no banco de dados ainda, então vou inseri-la. Agora, não estou apresentando
isso como uma alternativa
ao encarte Eu gostaria de
mantê-los bem separados. Se eu estiver inserindo algo, eu uso a função add Se estou atualizando, uso
a função de atualização ou apenas a acompanho adequadamente, mas o rastreamento nem
sempre é uma opção como a que vemos em
nossos aplicativos. Mas uma coisa a observar: se esse ID não estiver presente, ele será adicionado. É por isso que sempre nos
certificamos de incluir as informações de identificação
em um formulário para que ,
quando ele for enviado,
esse ID esteja presente
no registro para que possamos realizar essa atualização
adequadamente. Portanto, esse é um ponto muito
importante a ser observado. E mais um experimento é colocar um ID
que não existe. Então, se esse valor de ID estiver
completamente incorreto. Eu tenho dez, e sabemos
que só temos oito equipes,
certo , ou equipes com ID oito. Então, o ID dez está completamente errado. Ele tentará fazer a atualização, mas lançará uma
exceção nas alterações salvas, dizendo que a
operação falhou, bem, esperava afetar pelo
menos uma linha,
mas afetou zero Pode ter havido
alguma modificação nos dados nele contidos Então você pode ver aqui que não está realmente dizendo
exatamente o que está errado. Sabemos que isso
está errado porque o valor do ID não existe. E está dizendo que pensou
que faria pelo
menos uma mudança,
mas nada aconteceu. Portanto, não temos certeza do
que pode ter acontecido. Você precisa
ler a documentação. Mas, como eu disse, quero
ver o que pode causar esses erros para que, quando
tivermos erros um pouco vagos como esse, possamos supor que, ok, deve
haver algo
errado com alguns dos dados que
forneci em algum lugar Então, isso é realmente
tudo para a atualização. Como você pode ver, é uma operação bastante
simples. Você tem duas opções mais uma vez. Você pode encontrar o registro, fazer alterações e
depois salvar as alterações, e o rastreamento
permitirá que o COR saiba que,
ok, esse registro foi modificado, então eu tenho que criar a instrução de
atualização para ele. Porque mesmo que
tenhamos uma lista deles, se fizermos alterações em apenas um, ele saberá que apenas um
precisa ser atualizado, certo? E a alternativa, saber ou outra situação, pode ser que rastreamento não seja
necessariamente uma opção. E o registro que
atualizamos não está sendo rastreado
pelo FCR naquele momento, então podemos usar esse método de
atualização, que procurará
o registro e gerará a declaração
de atualização automaticamente Se não houver ID presente, o método de atualização
prosseguirá e adicionará o
novo registro. Ok.
17. Consulta simples de exclusão: E estamos de volta. Então, até agora, examinamos
todas as letras
no CRD, exceto o
D, que é delete Então,
analisamos como criar. Passamos algum tempo analisando como podemos recuperar e
as diferentes formas Acabamos de ver como
atualizamos e agora queremos
saber como excluímos ou removemos
dados do nosso banco de dados. Então, eu já
configurei dois métodos, um para mostrar um exemplo simples de
exclusão e outro em que mostramos uma exclusão quando há dados
relacionados. Tudo bem? Então, a simples exclusão. Vamos dar uma olhada nas opções que estão disponíveis para nós. E vou passar algum tempo com a tabela classificativa porque
temos que fazer uma limpeza Primeiro, temos duplicatas
aqui e aqui. E então provavelmente também
queremos remover a Bundesliga. Então é isso que vamos
fazer hoje. Tudo bem. Então, quando eu digo
ponto de contexto e escolho uma tabela. Então, neste caso,
é o ponto da liga
e, em seguida, comece a digitar Delete, ou melhor, remova meu erro, veremos que
temos duas opções Removemos e
removemos o alcance. Portanto, remova, adicione e atualize negócios com
um registro por vez
e, em seguida,
as operações de intervalo serão em massa. Tudo bem? Então, quando eu
disser remover e dar uma olhada no que é
necessário para fazer uma remoção, veremos que ela precisa que
toda a entidade seja removida. Tudo bem. Então, normalmente quando você está escrevendo
uma declaração q, você diria delete
from table we maybe ID seja igual
a um. Tudo bem. E então, basta
seguir em frente, pegar
qualquer registro que corresponda à condição que
me foi dada e excluí-lo. E sem essa condição, ele
simplesmente limpará a mesa. Então, pelo menos, há uma rede de segurança aqui em que
temos que fornecer a entidade ou a lista
de entidades a serem removidas, que significa que temos que fazer um esforço muito deliberado para saber se é isso
que queremos
remover durante o tempo de execução Portanto, o risco de apagar
o banco de dados é muito reduzido nessa
situação. Tudo bem. Então, é claro, se
precisarmos fornecer a entidade
que será removida. E se você apenas
olhar a documentação, ela diz que a remoção coloca a entidade em um estado
chamado excluída. Então, ele marca que ele foi excluído,
mas, como você sabe, nada acontece até que
chamemos de salvar alterações. Portanto, se eu precisar fornecer
uma entidade para esse registro
, é claro que preciso
encontrar o que preciso excluir. Então, vou colocar uma linha logo
acima daquela
em que estou
encontrando a liga com o ID quatro quatro porque essa é uma das minhas
duplicatas, certo? E este não tem
nenhum registro relacionado. Portanto, essa é uma exclusão simples. Apenas encontrando aquele
com o ID quatro, quando o obtivermos, podemos dizer que é esse que eu
quero remover. E então, como sabemos, dizemos salvar as alterações. Obviamente, usando o
ASIC para adicionar um s dois, a declaração do método, Tudo
bem, e pronto Então, quando eu ligar para aquela, vou comentar sobre a segunda ligação por enquanto. Quando executo essa operação, vemos onde rasgou consulta select para
recuperar
o registro e, em seguida, ela saiu
e disse: exclua das ligas a mesma
consulta que conhecemos e amamos Obviamente, com essa
cláusula were,
certifique-se de não limpar as
tabelas no banco de dados Tudo bem. É assim que uma
simples exclusão realmente funciona. Agora, o motivo pelo qual estou
diferenciando entre uma simples exclusão e uma exclusão com relacionamentos é que, quando temos registros
relacionados, uma operação de exclusão se torna
um pouco mais sensível Ou seja, há uma
configuração chamada exclusão em cascata, o que significa que se eu remover o registro
com uma chave primária, todos os outros registros que tiverem uma chave estrangeira para esse também
serão excluídos Tudo bem, então seria quase como deletar você de um banco de dados. Portanto, todos os cartões que você já possuiu e todas as
informações relacionadas a você também serão
apagados de várias partes do banco
de Embora isso possa ser bom
em algumas situações pode ser muito perigoso
em outras. Tudo bem. Então, nessa situação, se eu vou excluir a
Bundesliga com o ID nove, estou apenas repetindo
o mesmo código
do símbolo do O que faz a diferença é
que eu sei que tenho pelo
menos um time relacionado
à Bundes liga, certo? Isso significa que se eu
removesse a Bonds Liga
, essa equipe
também seria removida. Da mesma forma que
se eu removesse a Síria
, uma, duas, três
equipes seriam removidas. Agora, voltando ao nosso arquivo de migração apenas para que
possamos entender as regras de restrição quando a tabela de quatro equipes foi criada e a restrição de
chave estrangeira foi inserida,
por padrão, ele deu a ação
referencial de cascata por padrão, ele deu a ação
referencial Há outras opções
que podemos definir aqui. Portanto, pode dizer restringir, o que significa que você não pode
excluir nenhum registro que tenha registros relacionados
ou dependentes Definir Nulo significa que ele
definirá todos os outros registros, todos os registros relacionados. O valor
da chave estrangeira
agora se tornará nulo, certo Digamos que excluamos
o pai e
definamos todos os valores da
chave estrangeira como nulos E então você não tem nenhuma ação, que é, bem, diz, ignorar a restrição, e depois outra
que diz padrão, que definiria um
valor padrão posteriormente, certo? Então, vou deixá-lo
na cascata padrão,
mas, mais uma vez, essa pode nem sempre ser a
melhor situação E há momentos em que o
núcleo da estrutura de
entidades ao gerar a migração
realmente indica
que, se eu colocar a cascata lá,
ela pode apresentar
certos tipos de erros
porque, você sabe,
essa tabela pode
depender disso e daquilo que, se eu colocar a cascata lá, ela pode certos tipos de erros
porque, você sabe, essa tabela pode
depender e você obtém um tipo de
situação de referência circular ou tabelas diferentes com base nos
mesmos dados. Portanto, o CO meio que o avisará
em situações em que o design do
banco de dados pode não ser ideal para esse tipo de regra de restrição. Tudo bem. Então, com tudo isso dito, vamos tentar realizar
nossa exclusão na Bundesliga, que sabemos que tem uma
equipe relacionada e ver Então, quando damos uma olhada no
qua que é gerado. Não parece diferente do que vimos com
o anterior. Então você provavelmente está
se perguntando, ok, então onde está a segunda exclusão
do registro relacionado. Vamos verificar se isso aconteceu. Então, se eu atualizar as equipes, Bundesliga desaparecerá,
desculpe, as ligas, e se eu atualizar as equipes, isso significa que o Burn Portanto, a cascata ocorreu, mas nossos registros
mostram apenas uma exclusão Isso ocorre porque uma regra em cascata está realmente no engenheiro de
banco de dados Não é necessariamente
uma declaração ca que será
gerada. Tudo bem. Então, essa
regra de migração foi realmente definida no banco de dados quando
afetamos a migração. O próprio banco de dados
sabe que a regra é excluir todos os registros relacionados. Então, isso não tem nada a ver
com o FCR naquele momento. Portanto, essa é uma das
situações potencialmente perigosas
que você precisa conhecer
ao
criar um banco de dados, configurar suas migrações e realizar suas operações de
exclusão Saiba que, por padrão, ele dirá cascata, mas você sempre pode substituir
isso para restringir por
padrão ou algo
parecido por meio Então, é isso mesmo.
Nossas operações de exclusão, como você pode ver, é
bastante simples Só precisamos ir e
recuperar o registro. É mais do que provável que tenhamos o ID do registro que
precisamos excluir de qualquer maneira, vamos
recuperá-lo e depois
dizer que é o que
queremos remover, salvamos nossas alterações
e pronto
18. Rastreando Vs. Sem rastreamento: Ei, pessoal, bem-vindos
de volta. Nesta lição, analisaremos o
rastreamento versus o não
rastreamento para que possamos ter uma melhor compreensão do que está acontecendo
em segundo plano Eu já escrevi um
código que pode pausar aqui, replicá-lo, mas
vou explicar o que
cada linha está Começamos com o método chamado rastreamento
versus nenhum rastreamento. Nesse método, tenho
duas declarações, uma que estamos obtendo
valor do banco e estou apenas
chamando-o com rastreamento e outra em que o
obtenho sem rastreamento. Se você
observar atentamente as duas linhas,
a diferença que você
notará é que eu tenho um ponto como rastreamento na declaração O primeiro é o que estamos
acostumados para contextualizar equipes de pontos. Eu quero o primeiro registro
que tenha a identificação dois. Certo? Isso quase poderia facilmente
ter sido uma descoberta , exceto que o rastreamento An não funciona quando
estamos usando uma descoberta. Tudo bem? Então, se
tentássemos descobrir como
excluiríamos, atualizaríamos e assim por diante, podemos colocar um rastreamento
nesse tipo de declaração. Daí minha redação sobre
o primeiro ou o padrão. E então, para manter a consistência,
fiz isso nas duas vezes, certo? Então, sem rastreamento, posso dizer, me
dê a equipe. Então, não
rastreie depois de me fornecer,
por favor, não rastreie na memória, mas eu quero a primeira ou
padrão com ID oito. Agora, isso não parece intuitivo da forma como está escrito, porque
você provavelmente dirá, por que não digo, me dê a
primeira equipe com o rastreamento. A realidade é que, após a
primeira declaração ou a declaração padrão, tudo isso praticamente se torna o objeto que
estamos procurando. Então, em outras palavras, a
única coisa que posso fazer depois uma primeira estrela padrão e,
bem, estamos usando o acing. Então, vou colocar
isso entre parênteses. Então, depois que essa declaração
for executada, certo? E eu só preciso
fazer
isso porque é acc, se não estivesse agindo, então eu não
precisaria fazer isso, mas no final de uma
primeira operação padrão, começaremos a
interagir com os campos reais que
estão no objeto É por isso que o
rastreamento do Ano simplesmente não pode vir
depois dessa declaração. Portanto, temos que informar ao contexto
do banco que examina a tabela de equipes, não rastreia os itens, mas eu quero o primeiro
que atenda a essa condição. Essa é a declaração.
Agora, a vantagem real de não rastrear é que,
na verdade, ele libera um pouco
mais de memória e acelera o
desempenho, porque
você pode imaginar que, se estiver recuperando 100 registros, todos com rastreamento, FCR precisará
monitorar 100 registros,
e isso é apenas em uma solicitação O que acontece com todas as
centenas de registros que você pode estar manipulando
no sistema, certo Então, o motor FCR
precisa trabalhar ao longo do
tempo para rastrear tudo isso o tempo todo Então, em uma operação simples, como talvez você esteja apenas fazendo
uma leitura na lista, como se estivesse listando coisas
no banco de dados para seu usuário. Você sempre pode simplesmente
dizer não rastrear porque não precisa rastrear. Coisas que estão em uma lista
simples, certo? No momento, no entanto,
quando você estiver prestes a fazer uma alteração e fizer
uma declaração como essa
, sim, o rastreamento
estará lá. Você vai em frente e o
remove ou mesmo na atualização, o rastreamento estaria disponível após a descoberta para
que pudéssemos desculpar, esse é um método errado
para que pudéssemos, aqui está, fazer a alteração, e então ela está sendo rastreada
naquele momento para ser salva, certo? Mas, para grandes operações de
leitura, você sempre pode usar o
rastreamento Ano para reduzir a atenção que
o FCR
deve prestar a cada registro que
está sendo recuperado Agora, o que fiz depois recuperar os com
e sem rastreamento, fiz alterações em
seus respectivos nomes Então, vou mostrar
que podemos realmente
ver as entradas. Então, temos essa coisa chamada de rastreador de alterações como
parte do contexto, que basicamente nos mostra informações sobre qual entidade
está sendo rastreada,
qual é o estado dela logo
antes do salvamento das alterações
e, em seguida, vamos
dar uma outra olhada nela após o salvamento das Eu só fiz isso por precaução, mas tenho certeza de que isso será atualizado posteriormente de qualquer maneira Mas veremos “Tudo bem”. Então, vamos seguir em frente e executar. Eu defini um ponto de interrupção
na linha de salvamento de alterações e tenho as
variáveis no relógio. Então, eu tenho as entradas
antes de salvar e depois de salvar. Então, se eu der uma olhada
nas entradas antes de salvar, ela me dará
a visualização dos resultados e mostrará
que apenas um
dos registros que está rastreando
foi modificado, certo? Então, se eu expandir, você verá que o estado da entidade aqui
é modificado. Na verdade, temos algumas
enumerações fornecidas pelo FCR, onde podemos dizer ponto de estado da
entidade e você modificou,
adicionou e Qualquer coisa que praticamente fosse possível fazer
em um contexto bruto, podemos dizer qual
mudança está prestes a ser salva ou
em que estado ela está logo antes de ser salva Vemos aqui que o
registro com ID dois está em um estado modificado. registro com a identificação dois foi o que
recuperamos com o caminhão Fizemos a alteração e,
logo antes de salvarmos, ele vê que é a única precisa ser salva porque não
estávamos rastreando o
registro com o ID oito. Portanto, não importa a
mudança que fizemos,
ela simplesmente não importa. Então esse seria
o cenário que nos
deu essa situação em que
teríamos o registro, sabemos tudo
sobre o registro, mas então temos que
informar ao contexto que essa equipe ou esse registro
precisa ser atualizado, momento em que ele
começará a rastreá-lo. Então, enquanto estava aqui, não
estava sendo rastreado. Esse objeto está no mesmo
estado desse objeto, mas não
está sendo rastreado pelo EFC No entanto, se inseríssemos
a instrução
de atualização manual sem rastreamento
, quando ela chegasse aqui,
ela também seria listada como um registro
modificado a ser salvo. Tudo bem. Então, vou
passar por essa e depois fazer mais
duas etapas para que possamos
ver as entradas após salvar
e as entradas após salvar. Agora, ele só está
rastreando o fato de ter
essa entrada antes do salvamento. Não, está em um estado inalterado. Então, depois de salvarmos as alterações, elas se movem de qualquer
estado em que estavam adicionadas, excluídas ou modificadas, e foram movidas para
um estado inalterado Então, isso significa que a estrutura de entidades ainda
está rastreando isso, certo? Uma vez listado
aqui nas entradas, isso significa que está sendo rastreado Portanto, há momentos
em que você pode ter alguns problemas de simultaneidade quando talvez esteja realizando uma operação e, em seguida, salve
as alterações no registro
e, provavelmente, tente manipulá-las novamente
logo em seguida, e então você pode
receber um erro dizendo que isso já está sendo
rastreado pelo Então essa é uma
dessas situações. Então, às vezes você precisa impedir que ele seja rastreado, mas não
entraremos nesse nível de complicação,
pelo menos não agora Por enquanto,
queremos nos concentrar apenas no que o rastreamento faz de
diferente do não rastreamento. Então, como eu disse, em
um cenário em que você só precisa de dados para fins de
leitura
, a ausência de rastreamento cria um
cenário muito eficiente para você. OK.
19. Revise relacionamentos contínuos: Ei, pessoal, bem-vindos de
volta a esta lição. Queremos
analisar rapidamente nosso relacionamento de um para muitos e
como o FCR
facilita a definição desse
tipo de relacionamento e nos permite interagir
com registros relacionados Então, só para recapitular, temos nossa tabela classificativa
definida como esse modelo de dados e nossa tabela de equipe
definida à direita Portanto, sabemos que, seguindo
nossa convenção de nomenclatura, em
primeiro lugar, o FCO foi capaz de
inferir que
existia uma relação de
chave estrangeira entre esses dois O que é essa convenção de nomenclatura? Bem, em primeiro lugar, eu
teria indicado que o nome do campo é ID
da liga. Tudo bem. Portanto, temos a tabela chamada
Liga e a chave estrangeira. Apenas chamando-o de League ID, ele realmente inferiu que existe uma relação de
chave estrangeira Então, apenas como exemplo, se eu não incluísse
essa propriedade de navegação
virtual, ele ainda saberia que há uma
chave estrangeira apenas por causa da convenção de nomenclatura que eu usei neste
momento Agora, devido ao tipo de
dados que está sendo usado, estou usando t e t, por
padrão, não pode ser nulo Então você perceberia
que a migração
gerada teria um valor anulável Aqui está o
ID da liga, era a coluna, e um ullase cai, que significa que não pode ser
nulo no Bem, o C sharp suporta tipos de
dados anuláveis. Se eu dissesse em ponto de interrogação
, isso seria
automaticamente anulável Então, vou fazer
uma migração só para mostrar. Portanto, esta é a nossa migração e
migração que tornou o ID
da liga anulável E então, nesse
novo arquivo de migração, ele parece
diferente do anterior, e vamos
passar por mais migrações. Então, eu não estou focando no que
estamos vendo ainda. Só quero destacar que
a coluna alter agora está vendo que anulável
é igual a verdadeiro, tudo porque colocamos
esse Em C sharp, se você tornar
o tipo de dados anulável, é
assim que o
FCR saberá que é nulo ou anulável no SQL deveria ser Então, está dizendo que o novo tipo
antigo é TS, mas agora é anulável Então essa é uma das maneiras
pelas quais podemos tornar
uma chave estrangeira anulável Então, por que você gostaria de
habilitar uma chave estrangeira? Em uma situação como essa, talvez você possa ter um
time sem uma liga. Então, mais tarde, vamos
adicionar mais mesas, uma das tabelas que
vamos adicionar é um treinador, um treinador pode ser um treinador. Bem, tecnicamente, um treinador
pode ser um treinador sem uma equipe porque minha
profissão é que eu sou treinador, mas eu não tenho um
treinador de equipe no momento Então, eu estou na tabela de treinadores, mas eu simplesmente não tenho uma equipe Então, nesse ponto, esse ID de
equipe teria que ser nulo se eu não empregado em uma equipe
naquele momento Então, esse é apenas um exemplo rápido que veremos mais tarde. Mas, por enquanto,
quero me concentrar no fato de que podemos tornar essa chave
estrangeira anulável Agora, voltando à
nossa equipe, modelo de dados, fiz um pequeno ajuste
em que removi o número inteiro da chave estrangeira
e o substituí
apenas pela propriedade de navegação Isso também tentará
gerar um campo de chave
estrangeira legável O único problema aqui é que, embora o campo de chave estrangeira
seja gerado
no banco de dados sem ter
a propriedade na classe, não
há como realmente obter esse valor inteiro ou interagir
com esse valor de ID, certo? É por isso que,
para facilitar a vida, é melhor
interagir com os dois. Agora, eu tornei isso compreensível, mas não
quero necessariamente manter essa cadeia Então, o que vou fazer no console
do gerenciador de pacotes
é remover a migração. Então, provavelmente vimos isso
antes, quando
analisamos todas as opções ou todos os comandos
que podemos executar. Então, para fazer essa ação
, diz que está
aqui, remova a migração. Portanto, remover a migração sempre
tentará remover a última ou a mais
recente migração feita. Então, aqui está nossa migração mais
recente. Posso apenas dizer que remova a migração e isso eliminará esse arquivo. Observe, no entanto, que
se virem que eles estão dizendo que tudo foi revertido e está fazendo tudo o que
sabe que é necessário Portanto, a única coisa, porém, é que, se você já tiver confirmado essa migração
para o banco de dados
e eu removi, a migração se torna
um pouco mais difícil Mas isso é algo que também
analisaremos, então não se preocupe com
isso ainda. Agora, mais uma coisa que
quero destacar sobre essas relações de chave estrangeira é o fato de que,
no lado da liga, posso adicionar uma propriedade que é uma coleção de itens
que eu sei que estão relacionados. Então, quando montamos
o banco de dados, você provavelmente
notou o fato de que
a liga tinha uma
coleção e uma coleção Então isso pode ser uma coleção. Pode ser enumerável, pode
ser uma lista. Realmente depende de você, mas vamos apenas deduzir que uma
coleção de equipes está certa E eu vou chamar isso de
equipes, o que significa que a liga pode acessar automaticamente a lista de equipes relacionadas a ela.
Então pense sobre isso. Em geral, então, se você quisesse a liga e depois quisesse todas as equipes da liga, você teria que encontrar
a liga talvez por ID e depois selecionar
a tabela de equipes para dizer, me dê todas as equipes com
o ID da liga, certo Ou você simplesmente obtém todas as
equipes com o ID da liga, mas precisa se juntar
à tabela classificativa para obter os detalhes da
liga em que estão Então, já estamos meio
que fazendo isso porque, com a equipe, posso obter os detalhes
da liga em que a equipe
está envolvida. Veremos isso mais tarde. Certo? Mas apenas colocando
esse tipo de coleção aqui, posso dizer, me dê
a liga com o ID 1 e inclua
todas as equipes. Então, automaticamente, estou recebendo a liga, estou
recebendo o nome e estou reunindo
2030 equipes associadas à
liga em um único objeto. Então essa é outra vantagem. Então, vou
adicionar essa propriedade e vou deixá-la lá. Você pode fazer o mesmo
em seu modelo. E a última coisa que realmente
quero destacar é que quero reiterar a importância de seguir as convenções de
nomenclatura. Quando você não segue
as convenções de nomenclatura, na verdade está lutando
contra um sistema projetado para
ajudá-lo a fazer as coisas melhor Então, nessa situação específica, estou me referindo, digamos
, à chave estrangeira. Criação porque você pode ter outras ideias sobre o nome que
deseja dar a essa coluna de chave
estrangeira. E eu não vou dizer não. Suas regras de negócios
podem exigir que você use outro nome de coluna. Mas aí fica
difícil, porque se eu quisesse chamar essa liga de FK, sei que
isso quebraria algum outro código que eu
tenho em outros lugares Mas se eu fizesse isso, o que
aconteceria é que, quando
eu executasse a migração, ela ainda
geraria uma coluna chamada League ID porque o FC está
seguindo sua própria convenção, e então essa será uma coluna aleatória. Uma coluna aleatória chamada
liga FK que não tem absolutamente nenhuma afiliação
com a chave estrangeira Então, mais uma vez, eu só
quero reiterar, siga essas convenções de nomenclatura, e a vida será
muito mais fácil Agora, na próxima lição,
veremos os relacionamentos de muitos para
muitos e vou me aprofundar em
algumas das coisas incríveis
que o FCR pode fazer por
20. Como adicionar relacionamentos: Ei, pessoal, bem-vindos
de volta. Nesta lição, queremos começar a analisar
muitos ou muitos relacionamentos. Agora, o caso de definir um relacionamento de muitos
para muitos seria quando você
tem muitos, muitos registros relacionados
a muitos registros Dentro do contexto de nosso aplicativo de futebol,
ou banco de dados de futebol, temos que
levar em
conta o fato que serão muitas
partidas entre várias equipes. Muitas equipes jogarão contra muitas outras equipes
durante a temporada. Eu tenho na tela um bom aplicativo
útil chamado raw dot IO. É um aplicativo da web e seu uso é
totalmente gratuito. E o que vamos
fazer é visualizar nossa estrutura de dados Então, vou usar apenas
retângulos, simples e simples, e vou
chamar isso de uma liga e vamos
chamar essa de uma equipe Então, sabemos que temos
ligas relacionadas a equipes. Simples e agradável, basta usar
um r para conectá-los. Tudo bem? Então, temos
liga e equipe. Não, eu preciso de uma nova
entidade na mistura, e vou
chamá-la de Mach Agora, uma partida
será composta, e eu vou apenas escrever os campos e as entidades Já sabemos o que está
na liga e na equipe, mas este
vai ter uma identificação. É claro. Também terá
equipe da casa e equipe visitante. Podemos dizer não, estou
meio que me
afastando da convenção de nomenclatura, Então, equipe da casa, equipe visitante, e
provavelmente teremos tempo. Como eu disse, vamos
acabar com o mesmo time da casa, o mesmo time sendo o time da
casa várias vezes e o mesmo time sendo o time
visitante várias vezes, mas eles estão se
enfrentando. Então, essa relação de
muitos para muitos realmente precisa do que
chamamos de tabela vinculadora, que é uma tabela que ficará entre as duas tabelas
relacionadas Nessa situação específica, porém, o excesso é, na verdade entre muitas equipes
e muitas equipes. Então, isso significa que temos uma equipe relacionada
a esta tabela duas vezes.
Então, me perdoe se você é novo
no desenvolvimento de banco de dados, mas é assim que funciona. Às vezes, você tem
duas chaves estrangeiras para a mesma tabela de
outra tabela, certo? Então, uma tabela tem duas chaves
estrangeiras aqui. Temos uma chave estrangeira
para a equipe da casa, no entanto, uma
chave estrangeira para a equipe visitante. Mas isso
realmente quer dizer que muitas equipes estão relacionadas a
muitas equipes, muitas a muitas. Tudo bem. Tudo bem. Agora que
visualizei dessa estrutura de banco aparência
dessa estrutura de banco
de dados e dessa nova tabela, podemos analisar e criar
os modelos para isso Então, eu criei uma nova classe que
vou chamar de match. E, assim como suas contrapartes
, terá
certas convenções de nomes Agora, antes de prosseguir, quero
apenas salientar que cada tabela ou cada
modelo tem basicamente esse ID. E há momentos
em que você terá
vários campos que provavelmente se repetem em todas as tabelas, como talvez quando você está
fazendo auditoria ou,
você sabe, você tem uma data de criação, esses tipos de campos que talvez todo mundo precise
ter, porque, claramente, todos os nossos campos, seguindo
a mesma convenção, todas as nossas tabelas, desculpe, temos um campo chamado ID Agora, eu não quero continuar repetindo isso em
todas porque, você sabe, se temos 20 tabelas, então são 20 cópias
da mesma linha de código Então, o que eu costumo fazer
é adicionar o que eu chamo, deixe-me chamá-lo de come on, e então vou adicionar
uma classe dentro de come on que eu chamo de objeto de
domínio base. Essa também não é uma
convenção de nomenclatura. Eu apenas chamo isso de objeto de
domínio base. As pessoas o chamam de objeto de dados
baseado, as pessoas o chamam de
objeto base, seja o que for. Mas isso realmente será
apenas uma aula abstrata pública. Só estou tornando isso abstrato
porque, quando é abstrato, não
consigo
instanciá-lo sozinho É realmente uma prova de falhas para mim, mas não precisa
necessariamente ser Mas vou pegar
essa propriedade de ID, colocá-la dentro do objeto do domínio
base
e, em seguida, todas as outras entidades podem herdar do objeto do domínio
base Dessa forma, não
preciso necessariamente repetir os campos. Se o nome do campo mudar, pelo
menos os
campos comuns em todos eles, eu só preciso fazer
a atualização em um lugar, mas todo mundo está herdando
desse único lugar, então todo mundo recebe o campo Tudo bem, então eu
vou fazer
isso por muito tempo. Então, não combina. Por padrão, tem uma equipe de campo de ID. E eu não vou
removê-lo da equipe, mas vou
deixar a equipe herdar E então o que você
vai notar agora é que ele vai
começar a reclamar
que está vendo o ID aqui
e na classe herdada Isso significa que posso
remover o ID dessa classe com segurança. Então, esse é apenas um pequeno
truque que, se você ainda não estiver
praticando ,
pode usar para
garantir que não repita muito o código. Tudo bem? Então, vamos seguir em frente.
Temos o Match ID. Agora eu preciso de uma propriedade que
represente meu time da casa. Vou
chamá-lo de ID da equipe local. Mais uma vez, isso está
rompendo com a convenção de nomenclatura No vídeo anterior,
eu teria mencionado importância das
convenções de nomenclatura. Mas há
situações em que você realmente não
consegue seguir a convenção de nomenclatura,
porque quando eu ligo para time da
casa e o ID da equipe visitante, CR não sabe ou
não vai inferir que isso significa que estou me referindo à equipe e isso significa que
estou me referindo à Então, veremos como navegar por
isso em um momento. Tudo bem. Então, apenas adicionando o resto
das propriedades, eu adicionei as
propriedades de navegação que
corresponderão a
cada chave estrangeira. Então, temos a chave estrangeira, temos a chave estrangeira e, em
seguida, eu tenho a data e hora. Então, mudei para data
em vez de hora porque a data pode
capturar data e hora. Então, saberemos a data
e a hora da partida ao contrário do meu
design inicial, que dizia apenas a hora. Agora que temos essa nova
classe ou modelo definido. Sabemos que precisamos adicionar ao contexto
do banco de dados.
Temos que avisá-lo. Vou apenas
duplicar isso e adicionar o novo modelo ao conjunto de banco de dados
e vou chamá-lo de matches Mas eu tenho que fazer
algo extra. Então, mais uma vez,
rompi as convenções de
nomenclatura recomendadas Eu tenho que fazer um trabalho extra
para que ele saiba que, ei, você deveria
ser uma chave estrangeira. Então, vamos ajustar o modelo da equipe para ela
saiba que ela
deve ter duas listas, uma lista chamada jogos em casa e uma lista chamada jogos fora de casa. Agora, lembre-se de que fizemos
algo semelhante para uma liga. Temos uma equipe referenciando
a tabela classificativa. Então, sabemos que uma equipe
pertence a uma liga. No entanto, uma liga
tem várias equipes. Da mesma forma, uma partida pode ter um time da casa
e um time visitante. Então, um, um de cada vez
para qualquer registro ou linha. Mas então uma equipe pode ter muitos
jogos fora de casa e fora de casa. É por isso que precisamos nos
certificar de incluir essas propriedades de
navegação na lista. Agora, com base nisso, temos que informar à estrutura
de entidades que toda essa conexão
significa que existe uma relação de chave
externa entre a equipe e a partida Até agora, é claro, ainda alheio a tudo isso Então, o que vou
começar fazendo é substituir nosso método de criação de
modelo Então, temos a configuração. Isso significa que sempre que
você estiver configurando o contexto, isso é
o que você deve fazer. Bem, este está dizendo
que, sempre que você for
criar o modelo
ou fazer uma migração, na próxima vez que
fizer uma migração, certifique-se de ter essas
regras em vigor. Tudo bem? Portanto, não quero dizer que toda migração repita o código para eles, mas significa que sempre que
você estiver construindo o banco de dados e lidando
com o banco de dados, isso é o que eu queria fazer. Então é para isso que esse método realmente
existe. Então, vou remover
essa linha padrão
e, em seguida, teremos
que informar ao construtor
do modelo que nossa entidade. Então, estamos usando uma API fluente neste
momento para
definir certas regras, e você verá por que ela é
chamada de API fluente. Então nossa entidade chamada equipe, e então eu estou quebrando a linha para
não irmos muito longe. E vamos dizer ponto, e então você verá
várias opções aqui. Agora, eu me
empolguei e tentei
todas as combinações, mas nem todas
funcionam realmente. Então você só precisa saber
o que está fazendo. Então, nessa situação,
quero dizer que minha equipe tem muitos. Tudo bem. E então definimos
uma expressão Lambda, ponto, e eu vou
dizer partidas em casa Uma equipe terá
muitos jogos em casa. Isso é verdade. Em seguida, vamos
para a próxima linha com um. O que vamos inferir neste
momento, não, é que você terá muitas partidas em casa com um ponto, e então veremos
propriedades partidas em casa ou da entidade
da partida, viu isso É por isso que é
fluente, porque cada linha é baseada
na linha anterior Então, uma equipe tem muitos jogos em casa
e, em seguida uma partida inteira
ou uma
partida inteira só tem uma, e eu vou dizer que, se estou
lidando com partidas em casa, então ela só tem uma equipe em casa. Certo? E então eu vou ter
que dizer isso e ela tem uma
expressão Lambda de chave estrangeira novamente, ponto M, e então eu posso especificar qual chave estrangeira
facilita
que isso tenha muitas com um relacionamento sobre o qual estou falando Eu vou dizer que a
chave estrangeira é o ID da equipe local. E espero que você esteja
começando a ver que sabe, nomeando suas colunas corretamente Se isso não ajudar o FCR a
descobrir o que você quer, isso ajuda você a descobrir
o que você precisa fazer mais tarde Também vou
adicionar uma restrição
para dizer que ela é obrigatória
e, para finalizar, vou definir o comportamento de não excluir Já discutimos
o comportamento de undelete onde sabemos que é uma
configuração para o banco de dados Eu vou dizer cascata. Isso significa que, se eu excluir uma equipe, quero que todas as partidas
continuem com ela. Isso pode ou não
ser o que você quer
fazer , porque talvez,
para os arquivos, você queira manter a equipe e todos os dados da partida disponíveis. Isso depende de você e de suas regras
de negócios, é claro. Então, vou repetir tudo isso para a equipe visitante. E você verá que
ambos são idênticos. A única diferença, na verdade, é
que eu guardei os fósforos e as colunas
fora de casa onde
elas eram as colunas iniciais. E é
basicamente isso para definir as regras em torno desses muitos
ou muitos relacionamentos. Portanto,
algumas vezes você pode ter que sujar
as mãos assim. Nessa situação,
é muito original
porque, em primeiro lugar , não estamos seguindo a convenção de nomenclatura
com nossas chaves estrangeiras
e, em segundo lugar, é a mesma tabela relacionada a outra tabela duas vezes Em outra situação,
digamos, eu vou te dar
um cenário aberto aqui. Tínhamos uma mesa para
guardar os produtos. Tínhamos uma mesa para
armazenar clientes
e, em seguida,
outra mesa para armazenar os produtos que
os clientes pediram. Muitos clientes podem
encomendar muitos produtos. Portanto, essa
tabela intermediária precisa ter o ID do cliente e
o ID do produto. Tudo bem?
Pense nesse cenário. Agora, nesse cenário, é
um bom relacionamento limpo. É uma relação mais fácil de definir do que a que
tivemos que fazer aqui. E então, nessa
situação, na verdade, você só precisa colocar a propriedade
de navegação da lista em qualquer tabela. E então o FCR apenas
inferiria que há uma
tabela de produtos do cliente a ser Desculpe, eu comecei isso agora, mas deveria haver uma tabela de pedidos de
produtos do cliente ,
por exemplo, a ser gerada porque você
acabou de dizer que o cliente teria uma lista de produtos e os produtos teriam
uma lista de clientes. Então, ele saberá
automaticamente que preciso criar uma
tabela intermediária para muitos
e, literalmente, seriam
muitos sendo a lista demais. Portanto, existem
cenários diferentes e cada cenário pode ter
suas próprias peculiaridades Essa é a peculiaridade do cenário, e acho que é bom fazer o cenário mais difícil, porque pelo
menos você pode ver o que pode ser
necessário caso tenha dificuldades e seu cenário não seja
tão fácil quanto poderia Agora, com tudo isso
dito e feito, vamos prosseguir com nossa
migração e ver o que obtemos. Então esse é o nosso arquivo de migração. Está criando a
tabela chamada Matches. Temos nossas colunas
sendo definidas
e, em seguida, temos as restrições impostas
à equipe que indicam nossos relacionamentos de
chave estrangeira, certo Portanto, a chave estrangeira número
um está entre, está
na coluna Equipe AA
e está entre as equipes e esse ID
e exclui a cascata, e é a mesma
para o time da casa Tudo bem. Então, com
tudo isso feito, vamos atualizar nosso
banco de dados. Tudo bem. Então, se você atualizou seu banco de dados
exatamente como eu fiz agora
, você teria
recebido esse erro. Se você não fez isso, então me mande uma mensagem e me
diga que você não. Mas essa mensagem acabou de chegar
e, como eu disse antes, não
vou evitar erros porque esses
são os tipos de coisas que fazem com que as pessoas tenham medo desse tipo
de tecnologia Então, está nos dizendo que falhou ao executar o
comando DB, criar a tabela. E se eu rolar
até o fim, ele dirá que estou introduzindo uma restrição
ou introduzindo essa restrição, ela pode causar vários ciclos ou
vários caminhos em cascata Então, em outras palavras, o que está dizendo é que ter esse referencial, a cascata de ações de
exclusão, nessas duas chaves estrangeiras, pode ser problemático para a estrutura do Então, talvez ao projetar
o banco de dados manualmente, você provavelmente possa contornar
isso porque eu nunca
fui avisado
diretamente pelo SQL Server sobre
algo assim, mas o FCR está apenas informando que isso pode ser
problemático e há
um erro ao tentar
fazer isso por
você problemático e há um erro ao tentar
fazer isso por Então, o que podemos fazer e o que
faremos é simplesmente remover
essa migração sem parar, e seguindo a sugestão da EFC que esse
comportamento de exclusão é problemático, vou fazer uma restrição Em outras palavras,
você não pode remover uma equipe a menos
que tenha removido todas
as partidas anteriores. Tudo bem. E eu realmente vejo onde isso é razoável, porque quando
eu disse anteriormente que você exclui uma equipe
e ela automaticamente elimina as partidas, isso
pode ser problemático, E especialmente quando
uma equipe pode estar na ID
da equipe da casa
ou na ID da equipe A. E então, você sabe,
isso acabará excluindo dados de equipes que ainda
estão no sistema Então, essa foi uma
escolha de design ruim da minha parte. Não tem problema. I R nos avisou,
mas, mais uma vez, eu só quero ajudá-lo a entender o que esse
erro realmente significa. Então, se você ver esse tipo
de erro surgindo, talvez
seja porque
precisamos mudar esse comportamento de
exclusão. Lembre-se de que, por padrão, será em cascata. Portanto, mesmo que não
definíssemos cascata aqui, você provavelmente
ainda teria recebido esse erro Portanto, é importante
entender como
mitigar esse
erro, caso você o receba Então, vamos tentar adicionar
essa migração novamente. E desta vez você o vê
dizendo que é restrito. Isso é bom. Vamos
atualizar o banco de dados. E desta vez, eu
termino e, examinando isso
em nosso explorador de
servidores de objetos SQL, vemos que temos
nosso ID e nossas duas colunas de chave estrangeira
que não são legáveis Essa é uma maneira de estabelecer um relacionamento
minucioso. Como eu disse, pode ser diferente
com base na sua situação. Dada a estrutura
do banco de dados, isso é o que tivemos que
fazer para realizar tudo isso. Essas são
diretrizes gerais, é claro. Quando você está criando um relacionamento de
muitos para muitos, você pode basicamente seguir essas diretrizes e
ser
capaz de criá-lo, não importa o quão complicado ou
simples seja.
21. Como adicionar relacionamentos One-To-One: Ei, pessoal,
voltaremos nesta lição, falaremos sobre mapeamentos de tabela
um para um ou relacionamentos um
para um Então, eu já
criei um novo modelo de entidade, e estamos chamando um treinador, e um treinador
será usado para descrever a um com uma equipe
porque, em nossa situação,
em nosso banco de dados, um treinador só
pode pertencer a
uma equipe por vez
e, claro, a uma equipe Tem um treinador, certo? Mas então, se o técnico
for demitido amanhã, digamos
que essa equipe pode não ter um técnico e esse técnico
pode não ter uma equipe. Então, você sabe, esses tipos de regras ou restrições comerciais
exclusivas podem orientar as regras que
inserimos ou o design do nosso
banco de dados Então, vamos em frente. Já temos o coach herdando do
objeto do domínio base, como dissemos, objeto do domínio
base está fornecendo essa propriedade de ID por padrão, para que possamos seguir em frente e nos concentrar em todas as outras propriedades que são mais exclusivas
do coach Portanto, a primeira propriedade
de um treinador, como você provavelmente deve ter
adivinhado, seria o nome Agora, eu não estou ficando muito
complicado com o banco de dados, mas sabemos que temos
um treinador, um treinador vai ter um nome. Neste momento,
não vou incluir mais
detalhes
sobre esse treinador. Mas vou incluir o fato de que esse treinador tem uma
propriedade chamada Team ID. Portanto, esse ID da equipe, como
o nome sugere, será a
chave estrangeira para a tabela da equipe. Agora, nossa
equipe ou a tabela da equipe precisa ter alguma representação
de um treinador. E o que vou
fazer aqui, mantendo as coisas
bem simples, é apenas
referenciar o treinador. Então, desse jeito, o treinador vai fazer parte
de uma equipe ou, você sabe, relacionado a uma equipe, e o técnico também a tabela de treinadores também sabe
que está relacionado a uma equipe. Vou tornar isso anulável. Agora, quando eu estava falando
sobre as regras e assim por diante, passei pelo
cenário de que o treinador pode existir na tabela
sem ter uma equipe. Então, se eu não tornar
isso anulável
, será necessário Nem sempre é necessário
porque, se ele for demitido, ele ainda é treinador,
mas sem equipe. Então, estou tornando-o legável para que a migração saiba
que, no banco de dados, isso pode ser nulo Ao mesmo tempo,
em nossa tabela de equipes, apenas fazendo isso,
ele sabe que, ok, isso pode ser anulável, então não precisará fazer nenhum esforço
adicional para isso Agora,
as propriedades de navegação, mais uma vez, ajudam você a obter os detalhes
das entidades relacionadas Então, quando eu tenho uma equipe, posso obter os detalhes
da liga em que ela está. Eu posso obter os detalhes
do treinador. E eu posso pegar todos os
fósforos se eu precisar. Do ponto de vista dos treinadores, se estou olhando para o treinador, tudo o que preciso fazer
é a identificação da equipe Então, se eu quisesse poderia incluir uma propriedade de
navegação, vou copiar e colar para avançar mais rapidamente Eu poderia simplesmente incluir essa propriedade de navegação da equipe aqui para que,
se eu contratasse um treinador, eu também pudesse incluir
os detalhes da equipe, de todas as partidas
e tudo mais, certo? Então, vamos dar uma olhada
na migração que
podemos gerar a partir disso. Tudo bem, então minha migração
adicionou a equipe de treinadores um a um. Então, nossa migração é gerada e podemos dar uma olhada
rápida e ver que
estamos recebendo a nova
tabela chamada coach. E se você percebeu, na verdade
pulamos uma
das etapas mais importantes Não sei se você percebeu, mas ignoramos
o que eu
ensinei como uma etapa vital
para criar uma tabela, que é
incluí-la em nosso contexto de banco Não incluímos
nossa nova tabela chamada coach ou coaches
em nosso contexto de banco Então, vamos dar uma olhada nisso agora. O fato de eu ter dito uma tabela que está no contexto
do banco de dados, que ela faz referência a essa
classe ou
a alguma classe, à migração ou, claro, vai simplesmente criar uma tabela que represente o nome da tabela. Então, esse nome está sendo gerado com base no
nome da propriedade, que é coach. Portanto, essa pode não ser a melhor
abordagem se quisermos seguir padrão nossa convenção de nomenclatura padrão,
porque até agora, sempre
pluralizamos
cada Portanto, estou apenas ressaltando
que, ao adicionar essa propriedade de
navegação, EFCR inserirá ou
criará automaticamente toda
essa migração em torno criação de uma tabela para essa propriedade de
navegação Então, vou remover
a migração, no entanto, porque queremos
manter o padrão. E vou
adicioná-lo ao contexto do banco de dados. Então, temos uma mesa chamada Coach. Refaça a migração
e então poderemos nos sentir um pouco melhor com o
que está sendo gerado. Então, estou apenas
apontando algumas coisas que FCR meio que fará nos
bastidores,
mesmo que você perca uma etapa Então, você quer ser
meio deliberado, mas o FCR fará
certas suposições para você com base em como ele
sabe que Vamos prosseguir e atualizar
o e pronto. Então, eu só quero
salientar também que o índice de criação parece um pouco diferente do que
poderíamos ter visto
até agora, e ele tem um filtro. O ID da equipe não é nulo. Então, só de olhar para isso, você provavelmente está se perguntando,
ok, o que isso significa, especialmente porque dissemos à tabela que
o
ID da equipe é anulável Bem, se observarmos
a declaração que foi gerada para
o índice de criação, estamos criando o índice exclusivo nessa coluna quando
ele não é nulo Então, uma vez que há um valor, isso significa que você não pode repetir esse valor em nenhum outro treinador. É basicamente isso
que está dizendo,
mas é permitido que
seja nulo de qualquer maneira Ok. Então, isso é realmente tudo para estabelecer um
relacionamento individual. Mais uma vez, o
cenário para isso seria quando você
soubesse que só quer que uma entidade seja associada
uma vez a outra entidade. E existem
cenários diferentes quando você tem relacionamentos
individuais. Também pode ser que um seja totalmente
dependente do outro, ou
seja, pode ser um cenário
em que só queremos ter um treinador no sistema quando
ele está associado a uma equipe. Além de estar
associado a uma equipe, ele não deveria estar no banco de dados. Portanto, você
também tem esse cenário, mas, mais uma vez, suas regras de negócios e
seus requisitos
orientarão as
decisões que você toma durante o design.
22. Gere um novo diagrama de entidades: Ei, pessoal, bem-vindos de volta.
Este é um vídeo rápido. Eu só quero mostrar como você pode atualizar seu diagrama
de banco de dados. Então, estamos fazendo
algumas mudanças. Adicionamos novas tabelas,
adicionamos novos relacionamentos e eu só quero mostrar como
você pode atualizar a representação visual do
seu banco de dados. E
é bem simples. Da mesma forma que aconteceu
na primeira vez, basta repetir essa etapa e ela criará um novo
diagrama e o alterará para você. Então, basta clicar com o
botão direito do mouse no seu projeto. Vá em frente e vá
para o FCR Power Tools, adicione o diagrama de contexto do banco Ele simplesmente gerará um novo para você, e você o verá aqui. Então, temos nossas novas entidades
na forma de coach, e você notará que
as setas estão mostrando a cardinalidade
dessas relações, então você pode dizer de cara que isso está sendo visto como um a
um Isso é demais, e isso também é demais. Você também notará que as
propriedades de navegação foram atualizadas quando uma partida tem uma equipe
visitante e uma equipe da casa. No entanto, a equipe tem
listas de jogos fora de casa. E, claro, se você passar o mouse sobre qualquer um desses
blocos ou propriedades, eles mostrarão qual categoria é coleção de navegação, dependente da correspondência, e
seu tipo é lista de correspondências Portanto, esse é um ótimo diagrama de
referência para dar a alguém que talvez não necessariamente
entenda ou queira examinar cada aula para
ver exatamente o que está acontecendo Esse belo diagrama de visão geral é uma ótima maneira de
se familiarizar com qual referência é o quê e como essas relações
são formadas.
23. Inserindo dados relacionados: Ei, pessoal, bem-vindos de
volta a esta lição. Examinaremos
alguns exemplos de quando
precisaremos adicionar registros
que tenham relacionamentos. Então, anteriormente, quando
analisávamos nossos cenários de inserção, na verdade
analisamos um
e eu o repeti abaixo, que é adicionar novas
equipes com a liga. Nesse cenário, tínhamos uma
liga que ainda não existia, e depois tínhamos uma equipe, que também não existia, daí a criação, certo? E então adicionamos essa equipe ao passar pelo
objeto da liga. E então percebemos que, quando
ligamos para adicionar e salvar alterações, o que aconteceu foi que ela criou a liga que ainda
não existia
e, em seguida, inseriu
automaticamente essa
relação de chave estrangeira com a equipe. Assim, você pode revisitar
o vídeo de inserção e revisar o que aconteceu quando
fizemos essa operação Agora, tenho alguns
outros cenários que gostaríamos
de analisar. Uma é quando adicionamos uma nova
equipe com o ID da liga. E acho que esse é provavelmente um cenário
mais indicativo do que aconteceria em
uma situação de software Agora, quando estamos
adicionando uma nova equipe, adicionando uma nova equipe com o ID da liga, provavelmente é
isso que vai
acontecer a partir de uma interface
web, certo? Alguém está digitando
o nome de uma equipe e
provavelmente indicaria qual liga essa equipe pertence por meio de
uma lista suspensa Portanto, você teria
esse cenário se exigisse
que o usuário
inserisse os dois ao mesmo tempo, insira o nome da equipe
e o nome da liga. Então, sim, você pode criar manualmente
os objetos e , em seguida, salvar as alterações e
ambas serem confirmadas. Outro cenário mais prático,
porém, seria que
você tivesse a lista de ligas e, quando eles
selecionassem dessa lista, eles lhe
enviariam o ID da
liga que foi
selecionada, enviariam o ID da
liga que foi bem como o nome da equipe em
que estão participando Então, já temos algumas
ligas em nosso banco de dados. Deixe-me ir
buscá-los rapidamente. Assim, podemos
simular facilmente quais IDs
seriam os possíveis IDs para
um usuário selecionar Então, digamos que eles quisessem adicionar um novo time de futebol do Serre Então, nosso código ficaria mais ou
menos assim. Não precisaríamos criar
esse objeto de liga, mas criaríamos a equipe
e, em seguida, passaríamos
o ID da liga de oito. Então, nesse cenário, a
liga já existe. Sabemos que é identificação. Estamos
adicionando isso à equipe. Estamos adicionando o nome
a essa nova equipe, e essa equipe
vai para a Fiorentina, e então podemos ir
em frente e adicioná-lo, e então esse relacionamento
será Agora, um dos benefícios de ter relacionamentos e, bem, bancos
de dados
relacionais
são projetados para reforçar essa
consistência em seus Diminuímos
drasticamente o risco, mesmo que ainda exista, de ter uma liga que não existe ser
associada a uma Então, eu já observei o fato que fazemos uma exclusão em cascata Se excluirmos a liga, todas as equipes serão
excluídas, certo? Mas então eu não posso adicionar uma equipe
relacionada à liga com ID 50 quando vimos
que oito era o máximo. CO, bem, o
próprio banco de dados rejeitará que o
COR tente, o banco de dados apresentará um erro e, em seguida, o
devolverá Então, esse é um dos benefícios
de ter esse tipo de integridade referencial
forte
aplicada em suas tabelas Há pessoas
que não gostam,
mas você está usando um banco de dados
relacional Use isso a seu favor. Tudo bem, então esse cenário é o primeiro. Quando Orwell II, o cenário um era quando poderíamos simplesmente
colocar o objeto inteiro e adicionar os dois e a relação
teria sido criada ou os dados relacionados
teriam sido criados
em segundo plano Nosso outro cenário,
que é mais prático, seria
quando obtemos
o ID do registro relacionado
e o
passamos para o registro que
pretendemos criar. Agora, nosso próximo cenário
seria quando quisermos adicionar uma nova liga com equipes. Mais uma vez, esse pode ser um cenário em que você está criando a liga
e, você sabe, dá ao usuário a
oportunidade de adicionar uma nova liga, adicionar todas as equipes e
depois enviar uma vez. Isso significa que, nessa situação, você precisa criar
o objeto para a liga e
informar às equipes o que ela tem Assim como o
contexto do anúncio teria adicionado novos objetos
e
configurado os valores relacionais, seria o
mesmo cenário aqui Então, eu já
fiz essa função
em que estou adicionando uma nova
liga com equipes
e, em seguida, uma equipe R é igual
a uma nova lista de equipes. Então, digamos que isso é o que o usuário enviou, bem
como o nome
dessa nova liga. Então você pode dizer que eu
copio e colo, certo? Então, esta nova liga é CFA, abreviação de man Island
Football Association Vamos trabalhar com isso. E essas são algumas das
equipes que estariam no CFA. Então, quando adicionamos essa nova liga, que é um objeto do
tipo liga e tem seu nome e
sua lista de equipes, estrutura de
entidades fará o
resto quando salvarmos as alterações. No próximo cenário,
analisaremos a
criação de registros para nossas
tabelas de muitas ou muitas. Então, lembre-se de que
as partidas representam nossa tabela principal de
muitas equipes, onde muitas equipes jogarão
contra muitas equipes, certo? Portanto, essa função simplesmente
define uma lista do tipo de partida e tem algumas partidas
com o ID da equipe visitante, ID da equipe da
casa e a
data da partida. Tudo bem? Agora, estou meio
que fazendo dois por um aqui porque estamos
vendo como
criar o registro de muitos para
muitos. E lembre-se de que nossa partida ou nossa tabela de muitas opções
geralmente teriam o ID e a propriedade de
navegação. Então, da mesma forma que
poderíamos colocar o objeto para a
propriedade de navegação e
adicioná-lo ao banco de dados,
é da mesma forma aqui. Mas em um cenário mais
prático, essas equipes já
existiriam no momento em
que adicionássemos uma partida. Então, o que precisamos fazer
é ter certeza de que estamos referenciando os IDs corretamente Com uma
interface de usuário, é claro, você restringe os
valores que o usuário pode inserir a valores
que
provavelmente serão
válidos para reduzir quaisquer contratempos causados pelo banco de dados ao
tentar inserir os registros Tudo bem? Então essa é a primeira parte das 241 nesse cenário A próxima parte é o fato de
eu estar usando esse intervalo de adição. Então, Ponto, sempre
fizemos anúncios. Certo? Adicionar representa um. Estamos transmitindo apenas um objeto quando dizemos
adicionar ou adicionar uma sincronização. No entanto, quando dizemos adicionar um
intervalo ou sincronizar um intervalo
, podemos passar uma
coleção de valores, e todos eles serão
adicionados apenas quando salvarmos as alterações. Então, tradicionalmente,
em versões mais antigas, você provavelmente
colocaria isso em um loop para cada loop e, para
cada um na lista, você adiciona adiciona adiciona e
salva as alterações. Agora, agora, em nosso cenário final, não
há nada realmente
especial acontecendo aqui. Já sabemos como
adicionar um registro. E o fato de
termos um relacionamento de
um para um
nesse cenário não muda o fato de que
é o mesmo
trecho de código adicionar apenas um registro. Então, temos um treinador e nome
desse treinador
é Joseph Marino, e ele vai
treinar a equipe ID três Agora, lembre-se de que esse é,
na verdade, um campo legável. Então, digamos que tínhamos dois treinadores e um
não tinha uma equipe Então eu vou
dizer Antonio Conte,
e esse treinador não
tem uma equipe, certo? Da mesma forma que eu posso adicionar Joseph Marino
com o ID da equipe, eu posso adicionar Conte
sem a A única coisa é
que ele ficará meio órfão, ele
existirá na mesa, mas não tem nenhum
relacionamento com uma equipe Então, assim que ele for contratado, simplesmente atualizamos seu registro e ele terá esse
registro relacionado para a equipe. Então, do jeito que está, se eu executar isso veremos os dois treinadores sendo inscritos sem erros em
nenhum lugar Antonio sem o ID da equipe, assim
como Joseph
Marino com o seu Então, eu comentei
as outras funções. Deixe-me descomentar e, em seguida,
vamos executar todos eles e ver exatamente
o que está acontecendo no código Então, vamos tentar isso de novo. Tudo bem, então tudo foi
executado sem a Terra. Então, vemos que estamos adicionando a
Bundesliga no topo. Estamos adicionando Barn Munich, estamos adicionando Florentina,
estamos adicionando Então, você pode ver que mesmo
quando agrupamos os objetos,
o FCR, mais uma vez,
sabia de forma inteligente
qual é a dependência, Insert que obtém sua identidade de
escopo
e, em seguida, usa isso para inserir qualquer outra coisa Então, aqui vemos que estamos adicionando o
Rivoli United ao lado do CFA. Portanto, o CFA tem um ID de 11, e é por isso que Rivoli e
Waterhouse Esse cenário é que estamos adicionando uma liga com
a lista de equipes. Para aquele com as partidas
em que adicionamos o intervalo, você vê que ele simplesmente
examinou e adicionou cada uma individualmente. Você provavelmente está se perguntando
por que ele simplesmente não criou uma instrução de inserção
e a fez linha por linha. Bem, isso remonta
às operações em massa. A FCT decidiu que, a menos que você esteja lidando com um
certo número de registros, provavelmente não vale a pena agrupar esses comandos É por isso que, para comandos
menores ou um número menor de registros, você verá instruções
SQL individuais sendo executadas para eles. Então,
isso é realmente o que podemos fazer para inserir dados relacionados Mais uma vez, isso pode parecer
pouco intuitivo porque estamos codificando os dados e usando um aplicativo de
console Mas em um cenário de
aplicação web, lembre-se de que você
teria fornecido um formulário ao usuário, o que limitaria ou permitiria que
você o restringisse a inserir somente
valores de dados que
você sabe que precisa para realizar
as operações de salvamento. Então, quando eles preencherem
esses formulários e enviarem, você extrairá esses dados. Se é que eles estavam criando uma nova liga com uma
lista de equipes, bem, vemos como podemos fazer
isso com bastante facilidade. Certo? Essas são apenas diretrizes sobre o que pode acontecer
no back-end Depois de ter os dados que o formulário ou
o usuário prefeririam enviar por meio do formulário, você sabe como criá-los
e enviá-los ao FCR e deixar o FCR
fazer o resto.
Ok
24. (Carregamento de ansiedade) incluindo dados relacionados: Ei, pessoal, bem-vindos de
volta nesta lição, veremos como podemos recuperar dados de várias tabelas
usando um comando Agora, um cenário para
isso seria se você tivesse um relatório ou alguma exibição de dados que
precisa realizar, mas os dados
que você precisa exibir estão
espalhados por várias tabelas. Agora, primeiro, é
aqui que entra a
integridade referencial , porque você sabe que
sempre pode obter
os dados relacionados
de outra tabela Mas, se você estiver familiarizado
com o qua tradicional, também saberá
que precisa fazer alguma forma de junção Pode ser certo,
pode ser esquerdo, pode ser inérico, mas você
precisa fazer alguma forma de junção nessa consulta qua para
recuperar os Não é muito
diferente do que
veríamos com nossas consultas
simples de seleção, exceto que
veremos mais algumas coisas Então, eu tenho a
consulta de seleção simples aqui para referência, e sabemos que
executamos com ela para listar, e é assim que obtemos nossos dados. Vamos dar uma olhada em
alguns cenários que eu criei
para ver como
podemos contornar todo
o conceito de incluir
dados relacionados ou carregamento rápido Então, primeiro,
veremos como podemos obter muitos registros
relacionados. E o cenário aqui
é: e se
quiséssemos ter todas as
ligas e todas as equipes E pense em exibir esses dados para um usuário, certo? Você tem a lista de ligas e talvez, ao
clicar na liga, veja as equipes. Tudo bem? Então, você quer
recuperar todas as ligas e todas as equipes
relacionadas a elas, talvez tudo em uma chamada Por qualquer motivo,
seu cenário pode determinar por que você precisaria escrever
esse tipo de núcleo Não há problema. O Entity Framework Core nos
permite fazer tudo. Então, o que faríamos é,
como uma simples seleção, diríamos que
as ligas são iguais a, e então aguardamos nosso contexto, que
chamará nossas ligas, e então simplesmente diremos
para Então isso seria o que
faremos para conseguir as ligas. Agora, queremos as equipes
associadas às
ligas, certo? Então, antes de nossa lista, temos outra função que
podemos usar chamada include. Incluir nos permite inserir
uma expressão Lambda. Então você vê como as
expressões Lambda funcionam. Não, você vê que eles não são
exclusivos dos filtros e assim por diante. Há certas funções
que usam expressões Lambda. E você sempre pode dizer que uma expressão
Lambda será usada com base no tipo de dados, que é a expressão funk, e então você verá a liga ou
o objeto de qualquer
tabela Tudo bem? Então, estamos
basicamente dizendo: O que você quer que eu inclua? Isso é o que isso está
perguntando agora, e eu quero incluir o ponto Q, e então eu diria equipes. Então, logo de cara, veremos essa
pedreira sendo explorada para nos
devolver basicamente estrelas
selecionadas das equipes com
as junções
internas nos IDs das equipes correspondendo
ao ID da liga ou
da liga ou na tabela da
equipe,
correspondendo ao ID
da liga da tabela classificativa Então, vamos
dar uma olhada rápida nessa instrução SQL gerada. E aí vemos selecionar
e, em seguida, ele lista todas as
colunas das duas tabelas. Então, ligas é L e equipes é T, então ele seleciona todas as
colunas entre L e T e, em seguida, vai deixar as equipes
unidas
com o ID da liga correspondente ao ID da liga
da equipe Portanto, devido à integridade
referencial que aplicamos, F C sabe claramente como formular essa consulta
para saber quais colunas devem ser mapeadas entre si
na Observe que está usando uma junção esquerda. Isso significa que, se houver uma liga no
banco de dados que
não tenha equipes porque estamos
consultando a tabela classificativa, ela trará de
volta essa liga No entanto, o
objetivo da equipe será. Então, deixe-me colocar um ponto
de interrupção no final
dessa execução. Então você pode ver como
isso vai ficar. Então, esses são os dados que
retornam naquele objeto da liga. E se eu expandir,
você verá a ID 2, Red Star Premier League e
as equipes que estão na Reds Premier League e
todos os detalhes Então essa equipe não tem treinador. Tem o ID sete. Você vê que está relacionado
à Liga com ID dois e pode obter o nome. Então, aí mesmo, você pode dizer ponto do objeto
da liga,
ponto das equipes , e ele simplesmente acessa que
quiser
do objeto da liga Então esse é o poder
do nosso carregamento ávido. Portanto, temos alguns
outros exemplos que queremos analisar
apenas para mostrar como
você pode misturar e combinar
e as diferentes coisas que você pode fazer com
base na sua situação. Então, procuramos
obter muitos registros com seus muitos
registros relacionados, certo? Então, estamos recebendo todas as ligas e a lista de equipes por liga Isso pode não ser o caso.
Talvez você queira obter apenas um registro e um registro
relacionado ou, você sabe, uma lista de registros
relacionados, mas apenas um registro. Então, nessa situação, queremos ter uma equipe
e os detalhes do treinador. Então, para este, vou
dizer que nossa equipe está à altura, e aguardamos nosso contexto Como chama nossos métodos aqui. Então, se você observar o contexto, as equipes de
pontos incluem. Mas, como estabelecemos, mesmo quando dizemos equipes de pontos de
contexto, isso não faz nada até
colocarmos o comando de execução Agora, eu disse que
só queria um. E se você se lembra, a
maneira de obter um seria simples
ou padrão
ou primeiro ou padrão. Nesse caso, vou
colocar primeiro ou padrão. Então, eu quero uma equipe com
o ID, digamos, dois, e o treinador para
o time com o ID dois. Ou digamos três. Acho que coloquei a carruagem com identificação três. Podemos simplesmente voltar e verificar. Então, equipe com ID
três. Lá vamos nós. Então, vou dizer dot include depois colocar meu comando de
execução, que é, neste caso, primeira estrela padrão porque
essa é a execução Eu só quero um. Portanto, a
primeira estrela padrão usa a expressão Lambda, onde
vou especificar que
quero que a equipe com ID seja
igual a. Três. Tudo bem Então é assim que você encadeia
esses comandos. Estou apenas quebrando a
linha para que você possa ver onde cada função realmente
começa, certo? Então, contextualize as equipes, me dê todas as equipes. Inclua o treinador, mas eu só quero
o primeiro ou o padrão em que o ID seja
equivalente a três. Então, vamos dar uma olhada no que obtemos quando
executamos esse. Tudo bem, então Q que é
gerado é bem
simples Selecione top e vemos o mesmo tipo de junção
que está acontecendo. Então, por causa do primeiro padrão, estamos selecionando o primeiro
e, em seguida, temos essa cláusula
were para
filtrar até onde o
ID da equipe deve ser três Então, espero que você esteja vendo o tema
comum em andamento. Então, estou de volta no código
ou na janela do relógio. E você vê aqui aquele ônibus, a propriedade de navegação tem
todos os detalhes do ônibus. Então esse é o poder
da nossa inclusão. E uma coisa que eu
quero destacar, que é algo que pode ser frustrado se você não
perceber o que está acontecendo Onde você coloca o
primeiro ou o padrão
tem muito a ver com se a
instrução funcionará ou não. Isso só lhe dará um erro. Portanto, se eu colocar
equipes de pontos de contexto primeiro ou padrão, não
posso incluir depois um primeiro ou padrão
porque um primeiro ou padrão realmente
transforma isso em um objeto do tipo equipe
e, em seguida, tudo o que posso acessar
são as propriedades. Porque estou usando a sincronização A
que não está sendo mostrada, claramente, então deixe-me
tirar o ASIC e mostrar para você Que quando digo ponto, na
verdade estou apenas recebendo
as propriedades, a casa corresponde ao ID, certo? Então, se isso é o que está por vir ,
se é o que vem
depois ou o padrão, é claro que a inclusão não está nesta lista. E então acabamos com esse erro de
sintaxe nesse ponto. Agora, nos meus primeiros dias, eu não gostava muito e costumava pensar que a estrutura de
entidades tinha erros,
mas, na verdade, a
ordem é importante, certo Então, você quer fazer todas as coisas relacionadas ao
banco de dados
e, em seguida, deixar sua instrução
de execução por último. Tudo bem Então, mais uma vez,
vamos pegar as equipes,
incluir o treinador
e, em seguida, primeiro ou padrão, e essas linhas vermelhas
são porque eu preciso da sincronização A,
e pronto. Tudo bem, pessoal. Então, para o
nosso próximo cenário, analisaremos a inclusão dos netos Então, quando falamos
sobre netos, é só uma questão
de hierarquia A primeira tabela que estamos consultando, digamos
que seja a principal Então, a primeira mesa
ou a próxima tabela que incluímos é a criança. Mas então podemos ter
várias inclusões. Portanto, todas as crianças
têm relações
diretas de chave estrangeira com relações
diretas de chave estrangeira a tabela principal que está sendo consultada. Então, essas são crianças. Assim, você pode ter várias
inclusões apenas para as crianças. No entanto, pode
chegar um momento em que você precise de
dados adicionais da criança
e, em seguida, precise examinar outra tabela relacionada a essa criança. Então, nessa situação, teremos que
colocar equipes e depois partidas. E então, quando recebemos
os jogos, você sabe, ou
chegamos em casa
ou fora. Mas então precisamos dos detalhes
da equipe adversária. Então, se eu sou o time da casa, preciso
dos detalhes do time visitante. Se eu sou o time visitante, preciso dos detalhes
do time da casa. Então, vou ter que falar com
os netos
porque as partidas
terão as propriedades
de navegação do time da casa
e do time visitante. Então, mais uma vez, deixamos nosso método de
execução para o final e fazemos todas as nossas inclusões
antes de chamarmos a parte
final dele Então, vou começar
com quatro,
quatro partidas fora de casa. Tudo bem Então, eu sou a equipe número um. Queremos ver todas as partidas
do AA. E então podemos ver isso. Mas quando incluímos
as partidas fora de casa, tudo o que vemos são
os detalhes da própria equipe que temos, mas não sei
nada além da identificação do time da casa. Assim, eu posso encadear e dizer, depois
incluir e depois incluir me dá acesso às propriedades
da criança. Então, include me deu acesso
à propriedade de navegação da tabela ou do objeto
que representa a tabela. Eu me dei acesso a essa propriedade
de navegação. Agora, quero incluir uma propriedade de navegação
nessa criança. Então, posso dizer que inclua e use a expressão Lambda mais
uma vez e diga Q dot, e posso procurar o time da
casa. Lá vamos nós. Então, eu tenho partidas diurnas e partidas fora
de casa, que são do tipo partida. Quero incluir detalhes
sobre o time da casa. Ok. Por outro lado, eu disse anteriormente que todas as crianças podem ser
incluídas lado a lado Então eu tenho que incluir, e então eu tenho isso e
depois incluir, certo? Então, o que eu vou fazer, eu não quero
confundir a questão Deixe-me mostrar
várias inclusões para várias
propriedades de navegação antes mostrar os netos Então acabamos de ver um exemplo
do neto, certo? Mas estou apenas dando
um passo atrás e mostrando que
você pode dizer incluir quantas vezes precisar para incluir propriedades diretamente
relacionadas. Então eu posso dizer, dê-me as equipes e para
cada equipe que você
me der partidas do jeito deles e
todas as partidas em casa. Mais uma vez, porém, quando é uma partida em casa ou fora de casa, preciso dos detalhes
do time da casa. Quando é uma partida em casa, preciso dos detalhes
da equipe visitante. Então eu posso dizer que, depois de incluir
os jogos em casa, eu quero que você inclua os
detalhes do time da casa. Da mesma forma, quando
for uma partida em casa, quero que você
inclua os detalhes da equipe visitante. E então podemos
chamar nossa execução. Então, quer o chamemos primeiro, padrão
ou para listar
, a questão é que essa é nossa consulta para obter
nossos netos E então o problema
é que você pode realmente encadear isso
porque, você sabe, com base na configuração do seu banco de dados, você pode ter
várias tabelas com filhos sobre filhos ou chaves
estrangeiras sobre chaves estrangeiras. Contanto que você tenha uma chave
estrangeira envolvida, você pode dizer, depois incluir,
você pode incluir. Mas lembre-se de que a
inclusão permite que você
faça referência direta às chaves estrangeiras
relacionadas à tabela principal. E então, para cada
inclusão, você pode dizer, depois incluir e, em seguida continuar a
incluir e incluir. E observe que eles então incluem não
me impede de fazer uma
inclusão depois, porque mesmo que eu fizesse
tudo isso em uma linha,
é um pouco menos legível, é por isso
que eu o
dividi em duas linhas Mas veja o que estou dizendo,
me dê as equipes. Inclua a forma como combina.
Em seguida, inclua isso. Então eu vou voltar para incluir. Mas, obviamente, o
then include
só pode seguir o include
porque eu não posso incluir
depois de uma
tabela que não tenha a propriedade de navegação que estou procurando e espero
encontrá-la, certo? Então eu incluo a forma como as
partidas, então eu digo, quando você obtém as partidas do jeito, incluo o time da casa
pela forma como combina os objetos. Então eu vou em frente e digo,
inclua também praticamente
os jogos em casa. E quando você incluir
isso, eu quero que você
inclua os detalhes da equipe
visitante. Depois de formular
tudo isso, eu só quero aquele
com a identificação de um Então, vamos dar uma
olhada e ver o que obtemos. Então, primeiro, vamos prestar atenção ao SQL que
está sendo gerado. Temos todas as mesas
que estamos comprando. Então você vê, selecione T zero, T quatro, T dois, todos eles estão lá. E então temos de, mas
está usando uma subconsulta. Então, consultamos as equipes em
que o ID é igual a um e chamamos isso de t zero. Em seguida, deixamos a opção de junção ativada
e, em seguida,
selecionamos as partidas
e, em seguida, as
juntamos novamente às equipes Certo? Portanto, a complexidade
do SQL variará com base em como os
relacionamentos são realmente configurados. Nessa situação,
é quase como uma referência circular porque
estou olhando para uma equipe
e depois digo, você sabe,
quando estou vendo partidas, por favor, volte e
traga a equipe de volta. Então, é meio que voltar para
a tabela da equipe,
que acabou de consultar. Mas essa é apenas uma situação
com a
qual temos que trabalhar quando estamos fazendo esse
tipo de coisa. Tudo bem? Mas, mais uma vez,
você não
precisa se machucar
tentando resolver isso porque o
FCO o gerou para você Agora, o que retorna é a equipe com partidas
e adversários,
e isso deveria ter
sido um pedido de desculpas da equipe Mas então temos as
partidas AA, que são apenas uma. Então, essa equipe com ID 1, que é a Juvento, só tem uma partida AA e uma partida
em casa. Ok, tudo bem. A partida fora de casa,
sabemos o caminho da equipe. Isso está implícito porque
incluímos as partidas Way. Então, sabemos que somos a equipe visitante. Jovents é a equipe do caminho.
Não precisamos desse. No entanto, precisávamos dos
detalhes do time da casa, e entendemos. Então, aqui vemos que
é o InterMilan. E acho que o Jvento
tem uma boa chance porque eles nem
têm um treinador, certo? Então Javent pode simplesmente
vencer aquela partida fora de casa. Se olharmos para os jogos em casa, é a mesma situação. Somos o time da casa. Estes são os jogos em casa. Então, obviamente, Javent
é o time da casa. Mas se olharmos para a equipe visitante, vemos que a equipe
visitante é Asma, e o técnico é nulo, mas se tivéssemos
incluído o técnico E se quiséssemos incluir
o treinador junto com isso? Então essa é outra,
vamos fazer essa. E se, para cada equipe
que estamos incluindo, quisermos ver quem é o treinador. Queremos os detalhes do treinador. Então, posso dizer, mais uma vez, inclua. Então, quando
você inclui o time da casa, eu quero que você inclua Q, e então você vê que está apenas
descendo a cadeia e me dando as
propriedades de navegação de
acordo com o que vem a seguir na fila. Então, posso simplesmente dizer que
inclua o treinador. E então isso trará de volta os detalhes do treinador
dessa equipe. Então, deixe-me fazer isso de novo. E estamos no meio de uma
análise dos jogos em casa, então vemos que
somos o time da casa. A equipe A é A Roma, e o técnico do
Sarma é Joseph Moreno.
Então esse é um bom treinador. Teremos que lançar nosso jogo A para vencer
a partida em casa. Então é assim que você pode seguir em frente e encadear suas
inclusões para garantir que está obtendo todos os dados de todas
as tabelas relacionadas. E esse é outro
ponto forte de ter integridade
relacional implementada
adequadamente e trabalhar com o FQ Claro que está
tentando tornar sua vida o mais fácil possível. Então, isso acabou de reduzir um monte de junções e junções
internas para você, porque
se olharmos para esse SQL, ele ficou um pouco maior
porque agora temos que unir internamente ou à esquerda
o treinador na mesa Percebo que está dizendo forma
interna e deixada para somar. Portanto, ele sabe automaticamente
que, se for anulável, é uma junção à esquerda,
pois isso significa que pode não
haver nada naquele
lado da tabela No entanto, quando não
for anulável, ele apenas entrará
porque sabe que eles precisam ser totalmente compatíveis
para que eu traga Eu tinha esses dois outros
exemplos reservados, mas acho que meio que
esgotamos todos eles com
esses três, porque
esses três são bastante
abrangentes em termos do que estão descrevendo que você pode fazer quando se
trata Este diz que com filtros, já
filtramos aqui. Mas a ideia principal por trás mostrar um com
filtros seria que se eu dissesse, pegue todas as
equipes com partidas em casa. Portanto, é uma simples consulta. Aguardamos equipes com pontos de contexto, e vou adicionar a cláusula
where ao meu filtro, e aqui estou apenas
dizendo que partidas em casa, que sabemos que a
contagem de pontos da lista é maior que zero Então, isso significa que
me dê todas as equipes que têm pelo menos
uma partida em casa, e eu quero incluir seu
treinador. E, claro, é A. Então essa é a instrução SQL
que é gerada para nós. Você pode sentar e
dar uma olhada, é claro, se precisar. Mas então vemos que temos
três equipes
voltando sem
jogos em casa agendados. Então,
ao analisar os dados,
você pode ficar tentado
a dizer: Bem, por que não verificamos
se os jogos em casa são E quero dizer, eu entenderia porque estamos dizendo que home matches.com é
maior que zero E se eu tivesse dito, quanto é equivalente a nulo, já que esses são os
dados que vemos, mas como exatamente o FCO
seria capaz traduzir esse
objeto de lista em Porque lembre-se de que o SQL
não sabe nada sobre listas e
listas serem nulas Então, se observarmos
a instrução SQL está sendo gerada para isso, bem, em primeiro lugar, não há
dados voltando, certo? Portanto, essa consulta, seja qual for a
consulta gerada, não
está trazendo de volta
os dados que esperávamos. Não, se observarmos a
consulta SQL que foi gerada, veremos que é uma
consulta de seleção normal com a junção esquerda, mas esse filtro está simplesmente
aumentando Então, é claro,
uma maneira de dizer, não
consigo entender o
que você quer que eu compare
nessa situação, certo? Portanto, embora possamos não ter recebido um erro de sintaxe ou
qualquer forma de aviso, só
queremos ter cuidado ao adicionar nossos
filtros e, você sabe, podemos ficar um
pouco mais zelosos com a forma como estamos fazendo
isso, e É bom experimentar,
mas tenha cuidado. Então, isso é realmente para
explorarmos como consultar registros relacionados. E, como sempre,
vou deixar esse método lá para que você
possa consultá-lo mais tarde. Vou apenas esclarecer o que não
passamos, e você tem esses exemplos
para revisar depois.
25. Projeto, e tipos de dados anônimos: Ei, pessoal, bem-vindos de
volta a esta lição. Vamos dar uma olhada nas projeções e nos tipos de dados
anônimos Agora, você provavelmente está
analisando esse tópico e se perguntando, ok, do que exatamente
estamos falando aqui? Um estudo de caso para isso seria que você tem certeza de todos os
seus modelos, mas deseja
dados específicos de uma consulta
e, mais ainda, esse é o único dado que
você deseja retornar. Tudo bem? Então, você quer
ter um objeto personalizado com apenas bits de dados de todo
o conjunto de dados sendo retornados, e isso é tudo o que você realmente
deseja distribuir em seu sistema Então, vamos dar
alguns exemplos de, você sabe, quando você
provavelmente precisaria fazer
algo assim. Tudo bem, vou
mostrar três cenários que você precisa saber
como lidar com uma seleção. A primeira é quando
queremos selecionar uma propriedade. Como dissemos, talvez estejamos consultando toda a tabela da equipe Então, digamos que equipes. E seja uma
equipe ou várias equipes, o princípio
permaneceria praticamente o mesmo, onde temos que dizer contexto,
pontuar e obter as equipes. E então vamos trabalhar com
uma lista nessa situação, certo, que é claro que
temos que esperar Não, eu não quero tudo
fora da equipe, porque sabemos que o que
vamos receber é uma lista de objetos
com nome, ID da liga. E então, se incluirmos, então as outras coisas, certo? Eu não quero tudo isso. E se tudo que eu quisesse
fossem os nomes? Eu só queria a lista de nomes. Eu não queria nenhum objeto
complexo ou qualquer outra coisa, certo? Então, nesse cenário, o que eu teria que
fazer é adicionar uma seleção. Então, eu diria que o
contexto faz com que as equipes
selecionem pontos . E então, quando
eu faço isso, posso usar minha
expressão Lambda para especificar qual propriedade
eu gostaria de selecionar Então, se eu selecionar o nome e
, em seguida, executar as duas listas, essa é apenas uma lista
de strings. Tudo bem. Porque nome é uma string, e eu disse que quero a lista de
todos os nomes da equipe. Então eu recebo a lista
do tipo string. E isso vale para
praticamente qualquer pessoa que você faça. Então, se eu quisesse todos os
IDs da liga da tabela de equipes
, receberia uma lista de números inteiros k ao desaparecerem Lá vamos nós. Uma lista de números inteiros porque o
ID da liga é um número inteiro E isso é exatamente o que
aconteceria com qualquer coisa. Lista de treinadores. Tudo bem. Então é assim que você
seleciona uma propriedade. Agora, o cenário pode ser que você não
queira apenas uma propriedade. Você quer várias propriedades
e, mais ainda, provavelmente
quer várias propriedades de várias tabelas. Tudo bem. Então, vamos dar uma olhada na projeção
anônima. E se eu quisesse selecionar todas as equipes e incluir
todos os treinadores E tudo o que eu realmente
queria retornar, no entanto, era a lista de Bem, I contendo o
nome da equipe e o nome do treinador. Isso é tudo que eu realmente quero. Portanto, sabemos de nossa experiência
anterior com as inclusões que
acabariam fazendo algo assim, deixe-me dizer dot include. E então eu vou dizer,
certifique-se de me fornecer detalhes
do treinador ou o objeto do treinador
junto com a equipe. Mas então eu quero
selecionar várias coisas. Não consigo separar isso. Isso não funciona.
Não consigo dizer um cachorro. Então, sabemos em SQL quando você
quer colunas específicas. Tudo o que você precisa fazer é
dizer coluna, coluna um, vir coluna dois, etc.,
etc ., tudo antes do fm Isso não é realmente
uma opção aqui. É por isso que falamos sobre projeção em
outro tipo de dados Então, em tempo real, o que você pode
fazer é algo como novo
e, em seguida, você pode abrir um novo objeto diretamente
nessa instrução de seleção. Tudo bem. E então, se
você passar o mouse sobre ele aqui, ele diz que é do tipo anônimo Sabemos que C sharp é
fortemente digitado, certo? Portanto, tudo em C Sharp
é fortemente digitado. Ou é uma string, é
um int ou algo assim. Mas nessa situação,
estou apenas dizendo novo, não
há nada
depois do novo para dizer
um sabia o quê, certo? Portanto, é apenas um novo espaço em branco. Mas observe que não
há erros e está atribuindo a
ele um tipo anônimo Portanto, ele não sabe
qual é o tipo de dados. Ele só sabe que é algum
tipo que eu quero definir e tem uma propriedade do
tipo string chamada name. Então, ele já está herdando
o nome dado. Perto do campo. Então, nessa situação, Q representa a equipe. Então, se eu quisesse ser específico, diria que o
nome da equipe é igual ao nome do ponto Q. E então, se eu passar o mouse sobre ele novamente, você verá que ele evoluiu Diz: Esse tipo anônimo tem uma propriedade chamada nome da equipe. Tudo bem. Então, e se eu
quisesse o nome do treinador também. Então eu posso vir ou me separar
porque não, isso é um objeto. Então, deixe-me
dividir isso em uma nova linha para que você possa ver onde tudo
está acontecendo, onde tudo começa
e termina. Tudo bem. Então, aqui está nosso novo objeto sendo definido. Então, temos o Lambda Em seguida, estamos projetando
esse novo tipo anônimo e definindo a meta, quais nomes de campo ele tem
e quais valores ele obtém Então, o nome da equipe recebe o nome de que, e depois o nome do treinador, e não se deixe intimidar pelo fato de
que o que você está digitando não vem da inteligência porque, mais uma vez, estamos
fazendo isso rapidamente E vai
funcionar conosco, ponto, e depois pode dizer o nome do
ponto coach. Então, haverá duas propriedades, nome
da equipe e nome do treinador. Se eu passar o mouse sobre as equipes
, você verá apenas uma lista
desse tipo de dados anônimos, certo? E então estamos apenas
projetando isso em uma lista. Então, depois disso,
posso dizer quatro cada, e vou fazer quatro
aqui para imprimi-las, para cada item
na lista de equipes. Eu posso consolar pontos na linha direita. E imprima a equipe e coloque o nome
do item ponto da equipe, e eu farei uma torta como delimitador do treinador e do
item ponto do nome do treinador Então, mesmo após essa
projeção e essa criação muito aleatória e
espontânea desse objeto anônimo, podemos acessar facilmente as
propriedades que foram definidas Então, se eu modificar sua definição, item perde de vista o nome da equipe era
uma propriedade, certo? Então, acho que é o mais
flexível possível, e às vezes pode ser muito conveniente
fazer isso. Tudo bem? Agora, há um
estudo de caso para isso, e ele pode ser muito útil,
como acabei de dizer, mas, pessoalmente, prefiro ter uma projeção
fortemente digitada, significa que eu sempre sei
os tipos de objetos com os quais estou interagindo
sempre
que executo uma consulta Então, como eu disse, pode
haver um caso em
que você precise de um objeto personalizado, e isso é bom para um
cenário dinâmico. No entanto, em um projeto maior, você quer ter um pouco mais de
controle do que apenas ter esses novos objetos anônimos em
todo lugar. Então, o que você gostaria de fazer é ter uma classe fortemente digitada, e o que
vou fazer é criar uma nova
pasta dentro do domínio Ele não deve estar
dentro do domínio, mas vamos trabalhar com ele. Vou chamá-lo apenas de modelos. Por certo, você provavelmente gostaria de
criar um novo projeto, mas esse é um projeto de demonstração muito
pequeno. Eu não vou para o Velho Oeste com
vários projetos. Mas em um projeto maior, você
não quer ter isso em um espaço dedicado que não se misture
com seus objetos de domínio. Mas eu estou chamando os modelos porque, na verdade, eles são
modelos dos dados. Então, esse é um modelo
dos dados do banco de dados, mas o que
vou criar é um modelo provavelmente semelhante aos dados personalizados
que eu sei que espero. Então, digamos que um modelo seria uma cla chamada Team
detail. Tudo bem? Portanto, os detalhes da equipe terão algumas propriedades. Digamos que os detalhes da equipe tenham
o nome da equipe. Vai ter
o nome do treinador
e vai
ter o nome da liga. Esses são três pontos de
dados diferentes dos que
conseguiríamos obter apenas executando uma consulta normal. Teríamos que incluir
tudo sobre o treinador e tudo
sobre o nome da liga. E então pode ser meio irritante
receber quando
dizemos equipes de treinadores de equipe Então, você quer
ter apenas um objeto em que tudo esteja
lá para você. É por isso que eu o
chamo de modelo. Tudo bem? Assim, podemos projetar
nessa consulta fortemente tipada. Então, vou
copiar essa consulta inicial. Deixe-me dizer
a coisa toda. E vou adicionar e
incluir para a equipe. Então, lembre-se, é a sua consulta, qualquer que seja o dado que você
precisa, você vai buscá-lo. Então eu preciso da equipe, desculpe,
da equipe da liga. Então, estamos analisando a tabela de
equipes e incluindo
os detalhes do treinador e os detalhes
da liga. Em seguida, vou
selecionar
uma nova instância de detalhes da equipe. Então, éramos anônimos no topo, mas agora
sabemos o que somos abaixo. Os detalhes da equipe têm nome. Também tem o nome do treinador
e, em seguida, o nome da liga. Vou dizer o nome do ponto
da Q League. Do morcego, quando
observamos o que está sendo devolvido, temos certeza de que estamos recebendo objetos do
tipo detalhe da equipe. Portanto, não precisamos
adivinhar, soletrar e dizer que tipo de dados
posso esperar desta vez Ou não precisamos
necessariamente ir até
a definição para ver
quais eram todos os campos do tipo
anônimo no momento
em que o desenvolvedor fez isso, porque quando temos uma classe
fortemente digitada, sempre
podemos simplesmente
olhar para essa definição de classe E quando sabemos que estamos
obtendo esse tipo de dados
, sabemos
como trabalhar com ele de cara. Tudo bem. Então, vou conectar tudo isso e, em seguida,
dar
uma olhada nas diferentes
instruções de QO que estão sendo executadas para cada uma e quais dados
estão voltando Tudo bem. Então, olhando
em nosso console, podemos
passar por isso lentamente. Nosso primeiro comando, que
foi selecionar uma propriedade. Vemos que está dizendo
selecione o nome T da equipe. Tudo bem? Simples Você quer uma propriedade
ou uma coluna. É assim que é
feito. Não tem problema. Na próxima,
dissemos que queríamos nome e o nome da equipe
e o nome do treinador. Tudo o que fizemos foi dizer, selecionar esse tipo anônimo e especificar as
colunas que queríamos. FCR gerou exatamente
a declaração necessária para obter
exatamente esses dados Então, selecionou t
name como nome da equipe, que é o alias, certo? Então, chamamos o
nome do campo de forma diferente dentro do nosso tipo ou do tipo anônimo. Bem, ele deu o alias à
coluna dentro do SQL
e, em seguida, deixou a
junção adequada Já estamos familiarizados com
a inclusão. Então, na verdade, estou apenas apontando a segmentação das
colunas que queremos E então essas são as
equipes que voltaram. Vemos que Juventos tem Conte, Roma tem Joseph Marina e todos os outros estão em branco.
Isso é bom. Agora, para o próximo com uma projeção
fortemente digitada, é praticamente a mesma Estamos selecionando o nome T, o nome
C como nome do treinador e lideramos esse nome
como nome da liga. Então note que eu disse
nome, nome, certo? Portanto, não foi necessário
dar a essa coluna
um alias porque esse já é
o nome da coluna Então, o SQL não
deu a ele um alias, mas então o alias foi criado para os outros dois,
e então ele foi em frente
e fez as E então, quando o
imprimimos, vemos o nome da equipe, técnico e a Síria, a Síria, e estamos vendo todos
os detalhes da liga. Então, aqui estamos segmentando
as colunas que queremos. Portanto, será uma consulta
muito menor,
uma carga útil muito menor do que
simplesmente fazer com que cada equipe
e cada detalhe de cada inclusão sejam
trazidos de volta apenas uma vez Só vai dizer quais são os campos que estou selecionando ou nos quais
estou interessado. Deixe-me pegá-los e depois
trazê-los de volta como uma lista. Então, mais uma vez, embora
essa seja uma boa instalação, em um projeto, especialmente quando
você está trabalhando com outras pessoas, eu recomendaria que você se limitasse aos modelos fortemente tipados Talvez você crie um
modelo diferente por tipo de dados deseja
exibir na página para que, ao executar a consulta, você a extraia
diretamente nesse modelo
e essa página seja
modelada a partir desses dados E se você precisar
estendê-lo para você, basta estender seu modelo e estender
sua consulta de acordo.
26. Filtragem em registros relacionados: Tudo bem, pessoal, então estamos de volta e estamos
analisando outro tópico, e essa será uma lição
relativamente curta, na qual
falaremos sobre
filtragem com dados relacionados Agora, qual é o cenário para
filtrar com dados relacionados? Eu tenho uma consulta aqui e o nome da
minha variável está errado, então deixe-me corrigi-la para ligas E vou consultar a tabela de
ligas, mas estou consultando a tabela
da liga sobre algo que
a equipe possa ter Então, pense em um cenário em que
você mostra as ligas, mostra ao usuário
a lista de ligas, mas permite que eles
filtrem com base no nome da equipe Então, eu sei o nome da equipe
ou parte do nome da equipe, e quero ver em qual
liga essa equipe está. Então, isso significa que quando
eu clico em enviar, você precisa me dar a
lista de ligas onde
pode haver qualquer equipe que tenha um nome contendo
qualquer termo de pesquisa Então, imagine que esse era um termo de pesquisa vindo
do usuário, abreviado para Barn Munich, talvez E então estamos dizendo aqui. Então, deixe-me
reescrever essa consulta para que ela não
pareça
tão intimidante quanto provavelmente
parece, Agora, dizemos que contextualiza as pernas de
pontos onde. Todos nós estamos familiarizados com isso. Sabemos que temos
a expressão Lambda. E então eu vou dizer onde propriedade atende a
algum critério Nesse caso, o
critério é contra a propriedade de navegação,
que é equipes Então eu vou dizer
equipes de pontos Q E então é uma lista. Então, eu não posso muito bem dizer equipes com esse nome. É
uma lista de equipes. Então, vou usar any porque
any retorna um booleano
com base em alguma condição Então, vou dizer que, como já estou dentro de
uma expressão Lambda, não
posso reutilizar o
mesmo token Lambda Então Q aqui já está
empatado , representando um recorde da liga. Então, eu não posso usar Q novamente. É por isso que eu tenho o X. Pode ser S. Mais uma vez, a expressão Lambda, o
token realmente não importa, mas estou apenas mostrando por que eu tenho X em uma e Q na outra porque essa é um subconjunto da expressão Lambda maior Então, x ponto e depois
não, posso acessar as
propriedades da tabela da equipe. Então, vou dizer
onde está o nome, e então sabemos que o
ponto já contém, e então o termo de pesquisa, e então temos nossa instrução
de execução Então, isso é realmente tudo o que
há para
consultar registros relacionados, certo? Então, mais uma vez, as equipes
não são a mesa principal.
Essa é a mesa principal. No entanto, a operação
exige que
entremos na mesa infantil para
atender a alguma condição. Então, se olharmos
para isso, nossa instrução SQL que nossa instrução SQL que é
gerada apenas nos fornecerá a liga de
onde existe e tentará selecionar
a equipe com base
no termo de pesquisa ou com base no critério
que especificamos E então isso
nos devolveria uma liga,
que, se não me engano, seria Bundes
27. Como adicionar visualizações e outros objetos de dados: Bem vindos de
volta nesta lição, veremos como
podemos adicionar objetos SQL que
não são tabelas ao nosso banco de dados
por meio de migrações Agora, um estudo de caso sobre isso, usamos migrações
até agora para
controlar a maior parte do que
acontece em nosso banco Não queremos necessariamente
ter duas operações separadas, uma em que vamos
criar scripts manualmente
nas avaliações e outra que criaremos scripts
nas tabelas Portanto, seria bom se
tivéssemos apenas um ponto focal central em
nosso banco de dados, para que
sempre pudéssemos reverter e saber que tudo
o que foi feito na migração anterior pode ser desfeito por meio desse procedimento
específico Lembre-se de que
as migrações funcionam
como um controle de origem
para seu banco de dados Então, nesta
lição em particular, veremos como
podemos adicionar uma função, como podemos adicionar uma E, em
seguida, por extensão, a mesma técnica
que vamos usar para fazer tudo isso se aplicaria aos procedimentos
armazenados e a
cada tipo de função. Não vou entrar em detalhes sobre quais são
os scripts. Neste ponto,
presumo que você
já esteja familiarizado com
o que é a função,
a função escalar versus
a função com valor de tabela, bem
como com a forma como nossas
visualizações são Então, vou me
concentrar em como colocamos esse Qule na migração e, por extensão,
em nosso banco de dados Agora, como acontece com qualquer jornada em qualquer
coisa com o banco de dados, ela começa com a
adição de uma migração. Então, vamos acessar nosso
console de gerenciamento de pacotes, adicionar uma migração
e, em seguida, vou
chamá-la de adicionar visualização de detalhes
da equipe e função de partida
antecipada. Como eu sempre digo, você quer ser claro com suas mensagens de
migração. Não seja nem um pouco vago. Então, vou
adicionar essa migração. Não, eu não fiz nenhuma
alteração em nada com nenhum dos elementos
relacionados ao banco de dados. Eu não mudei o contexto. Eu não mudei
nenhuma das aulas. Então você percebe que
eles ficarão vazios
porque eu fiz uma migração. Eu não disse nada para fazer e ele não disse
nada para desfazer Então, temos que inserir manualmente o código para que ele saiba o que
fazer com o up e o que
fazer com o dom. Então, vamos ver como
adicionar a função. Então, eu vou obter
essas funções SQL. E eu vou dizer construtor de
migração. Então, o que teria
acontecido de
verdade é que eu
entrei no SQL e fiz isso. Entrei no
Management Studio, fiz a função
manualmente. Isso é bom. Mas, como eu disse,
não quero
adicioná-lo lá porque
quero um ponto de entrada para todas as modificações
baseadas no banco de dados daqui para frente, certo? Então, vou dizer ponto do construtor de
migração
e, em seguida, posso dizer SQL. Que vai usar um
parâmetro do tipo string. Portanto, ele espera
o comando cual como string de tipo ali mesmo Então, o que vou
fazer é usar meu sinal a para transformar essa string
em uma string literal
e, em seguida, colar a declaração
qual ali mesmo Então
é isso que vai parecer. Então, o construtor de migração Q e
, em seguida, você passa qualquer Q. Então, embora seja Q para
criar uma função É fundamental criar uma visualização como que estamos prestes a fazer ou
um procedimento armazenado, seja o que for, é tudo o que
você realmente precisa fazer. Então, vou copiar isso e repetir
essa etapa com a visualização. Então, nessa migração específica, espero criar essa
função e criar essa visão. Agora, eu disse isso e
já disse isso antes, então devemos estar familiarizados
com o fato de que o aumento significa a mudança que
estou prestes a fazer. O down significa as
alterações que eu desfaço ou as coisas que eu faço sempre que essa migração
está sendo revertida Então, se eu tiver as
instruções create dentro do up, isso significa que preciso colocar as instruções
drop dentro do down. Então, vou fazer essa visualização de pontos SQL drop view do
construtor de migração
e, em seguida,
atribuo o nome e, em seguida, descarto a função com esse nome. Então, esta é a primeira
vez que colocamos nossas mãos, você sabe, aqui dentro
dos arquivos de migração. Vamos fazer uma atualização do banco de dados e
ver a mágica acontecer. E minha experiência não foi muito mágica porque eu tenho um erro. E ao olhar para isso, vejo que tenho um erro nessa linha. Então,
deixe-me corrigir isso. Eu fiquei muito zeloso e
repeti a palavra fósforos. Então, vamos tentar isso de novo. Você provavelmente o detectou e não recebeu
aquele erro perfeito. E nesse ponto,
tudo está pronto. E se examinarmos nosso banco de dados rapidamente
e observarmos nossas visualizações, você verá a visualização
aparecendo lá, bem como sobre a programabilidade
e as funções
e as funções escalares em que nossa
função que nossa Portanto, essa migração foi um sucesso. Agora, quando
voltarmos, analisaremos como podemos interagir com uma visualização. Posteriormente, veremos como
interagimos com funções e outras operações escalares em fazemos uma chamada e esperamos
dados, mas, com uma visualização não
é realmente um
comando, estamos consultando, e será
um pouco
diferente de como consultamos nossas tabelas, e há certas regras
que precisamos conhecer Então, quando
voltarmos, veremos as modificações
necessárias para isso.
28. Consultando entidades sem chave (como vistas): Ei, pessoal, bem-vindos
de volta. Nesta lição, vamos nos basear no que fizemos em nosso episódio anterior,
onde criamos dois objetos não tabulares qual
na forma de uma
função e uma visualização. Então, continuaremos
interagindo com a
visualização porque uma visualização em termos práticos
é realmente como uma tabela somente para leitura
do lado de qual Isso significa que gostaríamos nosso aplicativo
pudesse consultar essas visualizações da mesma forma
que podemos consultar tabelas regulares. Então, o que teremos que fazer é criar uma nova classe de dados
que corresponda à visualização e
adicioná-la ao conjunto de banco de dados. Então, eu já fiz isso, criando
uma nova turma. Eu o coloquei no projeto de domínio. Eu chamo isso de equipes,
treinadores, ligas, e acabei de acrescentar a visão de
palavras para que, à primeira vista, possamos dizer essa é uma visão Qualquer que seja o prefixo postfix,
isso depende de você. Não estou sendo prescritivo. Só estou dizendo que
essa é minha convenção
conhecer as tabelas de forma
diferente das visualizações. Tudo bem? Você também pode criar
uma pasta totalmente nova e colocar uma chamada de visualização, desculpe, e colocar todos os modelos relacionados à
visualização nela. No entanto, você
deseja separá-los, isso depende inteiramente
de você, desde
que estejam limpos e
facilmente identificáveis Agora, depois de criar
essa classe para representar a visualização e os
dados que retornam da visualização, o que queremos fazer é informar o contexto do banco de dados
sobre essa visualização. Então, vou
adicionar uma nova linha nesse contexto de banco de dados em que
vou dizer conjunto de banco de dados, dar a ele o tipo e vou chamá-lo do mesmo nome da
visualização no banco de dados. Em nosso programa dot CS, vamos seguir que temos
feito até agora, e acabei de criar uma análise de consulta de
método, que
terá o único propósito
de chamar o contexto, as equipes, os treinadores, as ligas e colocá-lo No entanto, veremos
se realmente recuperaremos
os resultados e se obteremos algum erro ao longo do caminho. Então, vamos dar uma olhada nisso. Agora, assim
que chega ao código, recebo essa exceção, diz que o tipo de entidade exige que uma
chave primária seja definida Se você pretendia usar
um tipo de entidade sem chave, você precisa explicitamente informá-la,
desculpe, que ela
não tem chave, Então isso é esperado, e esse é um erro que eu
queria que víssemos juntos, porque às vezes você é
pego de surpresa por esse erro e não
tem certeza do motivo pelo qual está
recebendo esse Então, o FCR, como vimos, prospera na integridade
relacional. Chaves primárias sendo
definidas como chaves primárias, chaves
estrangeiras sendo
definidas como chaves estrangeiras. E com isso, ele sabe
exatamente como fazer as consultas com eficiência,
como rastrear, se alguma coisa está sendo alterada e como
monitorar tudo o que acontece no contexto
durante nossa solicitação Então, de acordo com esse padrão, nossa nova tabela ou
nova entidade. Não sabe se é uma mesa. Ele não sabe se é uma visualização porque a adicionamos
ao contexto do banco de dados, mesma forma que adicionamos
todas as outras tabelas. Então, no que diz respeito à
estrutura de entidades, ela a tratará
como se fosse uma tabela. No entanto, essa
exceção estava dizendo que não vejo uma chave nesta tabela. Não podemos colocar uma chave
nela. Não é uma mesa. É uma visão e, sim,
não tem chave primária. Portanto, a exceção de que,
no construtor de modelos, precisamos informar
que ele não tem chave. Então, devo dizer que a entidade de pontos do
construtor de modelos com o tipo de dados
e, em seguida, simplesmente
especificamos que não tem chave. Então, quando está criando, sabe
que, tudo bem, estou ciente de que não
devo tentar rastrear isso. Se eu encontrar uma mesa ou
algo que corresponda a
isso, sei exatamente o que fazer. Agora, outra coisa que
gostaríamos de fazer
neste momento é dizer que duas visualizações e duas visualizações basicamente nos permitem especificar o nome
da visualização no banco de dados
que ela deve procurar. Portanto, isso é como uma precaução
extra para garantir que ele
não veja nada disso como novos elementos, assuntos
automotivos ou novos trabalhos, mas sim na próxima
vez que fizermos uma migração Eu só vou saber que, ok, bem, esse tipo de dados, esse tipo de classe ou esse modelo mapeia diretamente para
a visualização em nosso
banco de dados com esse nome. E não tem chave, então não faça nenhum rastreamento. Então, o que vou fazer é
executar esse pedaço de código
novamente, e vou
deixar esse ponto de interrupção para que
possamos ver o que está acontecendo
no rastreador de alterações Então, desta vez, atinge
o ponto de interrupção. Quando analisamos os detalhes, vemos que estamos
recebendo detalhes porque a visão está sendo
executada corretamente,
e estamos recuperando o treinador, estamos recebendo a
liga e estamos recebendo o nome que esperamos E então o contexto
realmente não sabe nada sobre nada
para rastrear, certo? No que diz respeito a ela, ela fez seu trabalho e está feito, e está seguindo em frente com a vida. Então é assim que lidamos com situações em que
não há chave primária
presente, porque você pode acabar com uma tabela sem uma chave primária
ou um elemento de ID como esse. Talvez você seja
forçado a lidar com um banco de dados legado em que essas coisas não estão
sendo aplicadas, exemplo, incentivamos você a aplicá-las
quando estiver usando núcleo da estrutura de
entidades do zero, porque essas
situações podem existir Mas quando você
tem algo que não tem chave, luta para lutar, então
esse é o remédio. Você o coloca no construtor de modelos assim que eu consigo encontrar um contexto, você o coloca no construtor de modelos, informa que não tem chave
e, em seguida, você pode
mapear diretamente para a visualização ou, se for uma tabela, você pode realmente dizer ponto para
tabela e especificar o nome. Portanto, pode haver momentos em que
você tenha uma incompatibilidade entre o nome da tabela fornecido no contexto
do banco de dados e
a tabela real Você sempre pode dizer à tabela
e depois dar esse nome a ela, da
mesma forma que fizemos com a visualização. Ok.
29. Consultando com o Raw SQL: Ei, pessoal, bem-vindos de
volta a esta lição. Veremos como podemos
executar consultas usando SQL bruto. Agora, até agora, escrevemos
tudo usando nosso link, sintaxe e nosso C sharp e
tudo foi perfeito Mas pode
haver uma
situação em que você precise
escrever um pouco de QL bruto, especialmente agora
que estamos lidando com objetos não relacionados a tabelas, e começamos a ver
que isso se torna um pouco mais complicado. Você sabe, como você executa esse procedimento armazenado
ou essa função? Como exatamente fazemos isso, mas mantendo todo o uso do núcleo
da estrutura de entidades. Então, aqui vamos
ver dois exemplos à medida
que avançamos nesses
diferentes cenários. Agora, temos duas
funções que
nos permitem executar comandos cuais brutos, que são de Q R e
de Q interpolados Agora, observe a sintaxe, o contexto das equipes Então, ainda temos que
especificar nossa tabela
e, em seguida, dizemos que a partir do QL R, podemos colocar nossa declaração cual bruta
e depois listar Agora, devo destacar algumas
das limitações aqui
e os perigos
associados a essa QL bruta Depois de usar
essa função, você realmente se abre para o potencial da injeção de SQL se não estiver tomando
muito cuidado. Então é por isso que eles te
deram do QL bruto e do SQL
interpolado, certo Então, veremos a diferença
em alguns instantes. Então, vamos dar uma olhada no que
recebemos de Q R. Acabei de comentar o que ainda
não estamos usando. E do SQL raw, temos que dizer algo
como selecionar estrelas das equipes meio
contra-intuitivo, certo? Acabamos de dizer que o contexto das equipes, e então devo dizer que selecione uma
estrela entre as equipes novamente. Mas vamos ver o que recebemos de
volta quando testamos isso. Agora, quando verificamos nossos resultados, vemos que
recuperamos a lista de equipes e estamos
recuperando tudo. Dissemos selecionar estrela, então vamos recuperá-los
e está tudo bem. Agora, o problema com o
SQL bruto é que ele precisa retornar colunas que correspondam
exatamente conjunto de banco de dados ou à entidade
por trás do conjunto de banco de dados. Então, em outras palavras, se eu
quisesse apenas os nomes
das equipes e dissesse, selecione o nome das equipes,
deixe-me simplificar. Identificação não é simples. Deixe-me usar o nome comum de identificação. Eu só quero duas colunas
da tabela de equipes. Se eu tentar fazer isso
, acabaremos com essa exceção dizendo
que há certas colunas não
representadas no
conjunto de consultas porque ele tentou consultar apenas duas colunas,
mas está esperando Então essa é uma das limitações desse comando SQL bruto. Então, número um, a
consulta ou o
conjunto de resultados deve retornar todas as
propriedades do tipo de entidade. Outra coisa é que os nomes das
colunas devem coincidir. Portanto, mesmo que eu listasse
todos os nomes das colunas, não
posso dar a elas aliases
que não sejam mapeadas de volta
ao tipo de entidade original
em nossa classe chamada equipe E outra coisa é
que não podemos interunir, não
podemos ter dados diretamente
relacionados No entanto, posso, neste
momento, dizer, incluir Ok. Então, depois de escrever
o SQL bruto, eu ainda posso fazer minhas instruções de
inclusão, e funcionaria
exatamente como sabemos que funcionará de
qualquer maneira, certo? Então, se eu fizer isso e
incluir o treinador, veremos nossas equipes, e acho que a equipe
número três tem um treinador e aí vamos, veremos a entidade treinadora sendo incluída na
forma de Joseph Moreno Tudo bem. Então essa é uma
das coisas que você pode fazer. Se você precisar executar isso
a partir do EQ raw e precisar de dados relacionados, saiba que você pode
incluir da mesma maneira Agora, você já está familiarizado
com o SQL neste momento. Então você sabe que se quiséssemos
adicionar um filtro, por exemplo, se eu quisesse encontrar
o clube de futebol em que o nome é igual
a essa variável, e já fizemos isso no passado
, aceitando a entrada
do usuário e depois usamos essa entrada do usuário para
o filtro, certo? Então, digamos
que queremos usar essa variável para nossa filtragem Sempre podemos dizer
onde o nome é igual a, e então
passamos nossa variável. Então, a interpolação
nos faria colocar esse cifrão
antes da string, e então poderíamos simplesmente
colocar nossos colchetes e colocar o
nome Agora, se dermos uma olhada
no QL que é
gerado para isso, veremos o que
não necessariamente vimos nas duas últimas vezes ele está gerando
nossa instrução SQL e está fazendo a junção esquerda automaticamente por causa
das inclusões. Mas então anote isso agora. O que estamos fazendo
aqui é passar estrelas
selecionadas de equipes em que o nome é igual a. E observe que ele está
passando o valor, mas não está passando com aspas, porque em SQL,
teríamos que colocar onde o
nome é igual a. Abra talvez um único valor e feche aspas simples quando
estivermos lidando com uma string. Como resultado, está reclamando que não consegue encontrar
a palavra-chave as porque A S roma está sendo
visto como um comando AS em questão. Então, para remediar isso, em nossa
string interpolada, temos que colocar nossas aspas
simples
ao redor Então, vamos tentar isso de novo. E desta vez estamos
atingindo nossos pontos de interrupção. Nossa consulta foi bem-sucedida. Mas, mais uma vez, se você observar essa consulta em comparação com as consultas
anteriores em que
fizemos a filtragem, perceberá que não
há parâmetros É passar o valor literal
diretamente para a consulta, por exemplo, uma má prática, injeção de
QL. Tudo bem? Então, se você precisar
pegar algum parâmetro e
usar um comando QL bruto
para executá-lo,
é isso que
vai acontecer,
e você precisa ter muito
cuidado, porque se alguém
passasse usar um comando QL bruto
para executá-lo,
é isso que vai acontecer,
e você precisa ter muito
cuidado, porque se alguém algum
comando malicioso como entrada,
você teria voltado à
estaca zero antes dos dias em você teria voltado à que a estrutura de
entidades foi
desenvolvida para
ajudá-lo a evitar a injeção de Qual. Em uma situação em que
empregamos os serviços de
seu primo próximo a partir de qual interpolated Se você olhar para este, ele está pedindo uma string formatável De qual está
solicitando apenas uma string, mas de sc interpolated está solicitando
uma string formatável, o
que significa que ela
aceitará apenas uma string que significa que ela
aceitará apenas uma E segundo, não precisamos tratar essa declaração do carro tão literal quanto fizemos agora, porque ela
vai interpolá-la Portanto, ele
manipulará automaticamente
a parametrização
do comando, para
que não precisemos colocar camadas únicas ao redor
do valor interpolado ou
injetado na string Então, vamos dar uma olhada
nessa igualdade e compará-la. Então, veja, acabamos
de ver este, onde ele passou
o valor literal Já o segundo, na verdade,
dirá selecione a estrela das equipes em que o nome é igual
ao parâmetro zero, e definiu
o parâmetro no topo. E essa é a
diferença entre de
bruto de escala bruta e
de escule interpolada Portanto, eu sempre recomendaria
que, se você precisar misturar e combinar variáveis para passar uma declaração cual bruta, use a interpolação qua para sua própria proteção
e
30. Adicione e consulta usando procedimentos armazenados: Ei, pessoal, bem-vindos
de volta. Nesta lição, veremos como interagir com procedimentos armazenados usando o núcleo da estrutura de
entidades Agora, o estudo de caso sobre
por que você
precisaria interagir com um procedimento
armazenado
vem do fato de que
talvez você esteja lidando com sistemas legados em que grande parte da lógica está em
procedimentos armazenados no banco de dados. Então, na reconstrução, você não
quer dobrar o trabalho, reescrevê-los,
basta reutilizá-los Então, nessa situação, você provavelmente só
precisa saber como fazer
chamadas de procedimentos armazenados do FCR. Então, eu tenho uma muito simples que construí para
o contexto do nosso
banco de dados, onde eu só
tenho o treinador da equipe SPG, e ele recebe um ID da equipe e depois retorna de tudo da tabela
do treinador Agora lembre-se de que, quando estamos
lidando com RWQul, precisamos retornar tudo o que corresponde ao tipo de entidade
correspondente Tudo bem, então você não
pode simplesmente dizer o nome. Se quiser listá-los,
você
precisa listá-los na ordem dos nomes das colunas com
os
mesmos nomes das colunas, sem Ss e nada. Assim como fizemos com nossas
visualizações e funções, a primeira coisa que
vamos fazer é criar uma nova migração. Eu adicionei uma migração dizendo que
adicionei o nome do treinador do SPG. Eu errei o nome da migração,
mas vamos continuar E então eu coloquei o construtor de
migração para criar o procedimento e, da mesma forma,
descartar depois. Assim, você pode prosseguir e fazer a migração e
seguir essas etapas, e então podemos simplesmente
atualizar nosso banco de dados. E então isso nos permite começar a interagir com nosso procedimento
armazenado Agora, em nosso arquivo CS do programa. Eu já
escrevi alguns exemplos de código, e o novo método
com
o qual estamos trabalhando é o procedimento armazenado. Então, no procedimento de armazenamento, eu apenas codifiquei um ID de equipe
e, em seguida, vou passá-lo
para
a instrução SQL bruta
e aguardar o resultado Agora, vamos dar uma
olhada na sintaxe. Eu digo await context
dot coaches do fc R, então eu chamo minha execução
para me chamar o treinador da equipe SPG, e então eu tenho Agora, observe que estou usando o SqulRW. Na lição anterior, parei de
condená-lo, dizendo que era ruim porque abre espaço para a injeção dupla A realidade é que se
baseia em como você o usa. Então, eu mostrei a você a
maneira ruim de usá-lo inicialmente, onde usei uma string
interpolada e passei a validade diretamente Então, tudo isso foi
traduzido em QL literal, que é a pior
coisa que você pode ter entre a entrada do usuário e
a entrada no banco de dados parametrização é sempre melhor, daí nossa preferência
pela interpolada Mas então vamos dar um
passo atrás e não condenar muito o SQL raw porque se dermos uma
olhada em sua sobrecarga, ele realmente diz: me
dê a string SQL e depois me dê
uma lista de parâmetros Então é
exatamente isso que fizemos aqui. Eu digo DBO dot SP get team coach, e então eu uso um espaço reservado E depois desse
espaço reservado após essa string, agora incluí
o parâmetro Então, quando você fizer isso dessa
maneira, ele realmente lidará com
a parametrização para você da mesma
forma que vimos Equal
Interpolateed Portanto, não é o pior
método e não é totalmente inútil, porque você provavelmente deixou a última
aula se perguntando Então, por que o colocaram
se é tão perigoso? Há uma maneira boa de
usá-lo e há um jeito
ruim de usá-lo. Então, eu te mostrei o caminho ruim. Aqui está a maneira melhor ou mais
recomendada de usá-lo. Então, vamos dar uma olhada nisso. Agora, quando
analisamos o que recebemos de volta, vemos que nossa consulta está sendo gerada
e parametrizada, como dissemos ou
esperávamos que fosse Então aí está pegando
esse parâmetro de três, executando um procedimento stird E então nosso resultado é informação de
Joseph Marina como treinador
da equipe com ID três. Então é assim que você pode
executar um procedimento armazenado. E basicamente é
assim que executamos comandos um
banco de dados que
são, bem, comandos de consulta. Estamos pedindo algo ao banco
de dados e
vemos uma devolução. Então, nessa situação, é
por isso que temos que executar esses comandos QL brutos
em uma tabela. Em cada situação. Agora, o que acontece quando
precisamos executar um procedimento armazenado
que não está
associado a uma tabela ou consulta
é algo que não está diretamente
associado a nenhum tipo de entidade. Portanto, precisamos de QL bruto em relação algum objeto que não esteja
associado a um tipo de entidade. É isso que
veremos
em nossa próxima lição. OK.
31. Executando o SQL não de consulta Raw: Vocês
voltarão nesta lição, veremos como podemos
executar comandos que não sejam de consulta no banco de dados. Então, um exemplo disso
seria quando queremos excluir ou atualizar algo que manipula ou
aumenta os dados, mas isso não
necessariamente retorna nada para nós porque não
estamos selecionando Então, até agora, estivemos selecionando
e selecionando. Vejamos o que fazemos
quando não estamos selecionando, mas precisamos executar
esse tipo de comando. Tenho na tela uma nova
migração de exclusão de equipe por IDP,
SP, abreviação de procedimento armazenado, e tenho o código para criar o procedimento armazenado
chamado excluir equipe por ID, que usa um
ID de equipe como parâmetro
e, em seguida, exclui
a equipe adequadamente Temos os
métodos ascendentes e descendentes para que eu possa pausar, replicá-los e depois atualizar os dados Agora, depois de concluir
isso com sucesso, você pode acessar o
programa dot CS e ver que já foi criado o comando method
execute non query. Agora, quando vamos
executar o comando non-query, há algumas coisas
que serão diferentes entre
isso e quando sabemos que estamos esperando um
conjunto de resultados e eu estou tentando exibir os dois conjuntos de código na tela possamos fazer uma
análise comparativa Número um, só
seremos informados de quantas funções
foram afetadas. Ao contrário de quando
procurávamos as equipes, sabíamos que estávamos
recuperando um conjunto de equipes com resultados. Nessa situação,
recuperaremos apenas uma
variável que diz número de linhas afetadas. Tudo bem. Então isso é tudo
que estamos recebendo. Essa é uma. Segundo, quando estávamos fazendo as outras em que sabíamos que
estávamos recuperando dados, sabíamos em qual tipo de entidade ou conjunto de
banco de dados
executá-los, porque você não
esperaria consultar a estrela
selecionada dos treinadores,
mas contextualizar essa equipe Sabemos que você
simplesmente receberia um erro ao
tentar executar esse
método por completo No entanto, nessa situação, como não sabemos
o que o
procedimento armazenado fará, não
sabemos com qual tabela ele está interagindo
diretamente Dizemos
banco de dados de pontos de contexto em vez do nome do conjunto de banco de dados de pontos de
contexto. Então, o banco de dados de pontos de contexto e os métodos que
obteremos serão
um pouco diferentes. No caso do conjunto de banco de dados, obtemos do CLR e
do Q interpolados Nessa situação,
obtemos o banco de dados dot execute SQL raw e ele tem uma versão
assíncrona Então, temos raw e
temos R A sync. Daí a inteligência, onde
está a Async. E então, da mesma forma,
executamos nosso Async
interpolado igual Portanto, temos a versão
interpolada
e a versão bruta Agora, já
exploramos o mau uso
do método bruto e
, quanto mais aceitável, o uso mais seguro do método bruto A mesma coisa se aplica aqui. Não sabemos qual será o
procedimento armazenado que faremos, mas sabemos que precisamos
passar algum valor, que
provavelmente virá do nosso usuário. Portanto, queremos
nos proteger e usar uma string formatada
com um espaço reservado, não a
string interpolada quando estamos usando a sincronização execute Q R A. E então, é claro,
se você não quer essa
responsabilidade adicional de pensar tanto, não tem problema. É por isso que eles deram
a alternativa você simplesmente passar a string
interpolada, e ela faz o mesmo por Então, vamos dar uma olhada no que
obtemos quando executamos esses
métodos. Tudo bem. Então, estou analisando a morte
que foi gerada e vejo aqui que ela foi
parametrizada com o ID de equipe dois, e tudo
parece o que eu esperava No entanto, está me dizendo
que falhou. Por que isso falhou? Isso é por causa dessa restrição de chave
estrangeira que eu tenho no registro Então, eu relacionei partidas com
a equipe com ID dois. Então eu posso usar esse.
Esses são meus dados incorretos. Deixe-me tentar novamente. Tudo bem, então estou ajustando meus valores
porque só quero
procurar algumas equipes que eu
sei que não têm partidas Portanto, não devemos ter nenhum erro de restrição de
chave estrangeira novamente. Deixe-me tentar isso de novo. E atingimos o
ponto de interrupção desta vez, o que significa que tudo
foi executado corretamente. Agora, se eu observar as funções
afetadas LC, uma. Se eu olhar aqui embaixo, vejo um. Portanto, ele apenas informa
que executamos
isso com sucesso, e esse é o número de
linhas afetadas. Então, se você quisesse que
algum sinalizador dissesse se
foi bem-sucedido ou não,
você sempre pode dizer que, o número de
linhas afetadas for maior que um, podemos dizer que foi
bem-sucedido. Tudo bem? Então, é
isso mesmo para executar instruções de comando QL
sem consulta usando QL bruto. OK.
32. Dados de transmissão de dados: Ei, pessoal,
voltaremos nesta lição. Vamos dar
uma olhada rápida em uma das estradas menos percorridas, mas que é essencial conhecer, que é como semear dados. Agora, a semeadura de dados, se você
não está tão familiarizado com
o que estou falando, é o ato de
colocar dados no banco de dados
no início Então, assim
que seu
aplicativo for instalado, talvez você precise de dados padrão, talvez como uma lista de países ou determinadas funções ou
como um usuário padrão, coisas assim, você
provavelmente só quer
que estejam no sistema
no momento da criação. Assim que o
banco de dados for criado, essas coisas devem estar lá. COR nos permite codificar isso para que, sempre que
nosso banco de dados estiver sendo gerado com esse
script ou executando o banco de dados de atualização para que
o banco de dados continue com
todas as migrações,
possamos realmente inserir
um código que será
visto como uma migração
para que, quando essa
migração for executada,
esses dados sejam automaticamente
colocados no banco de dados a
partir do código get o banco de dados continue com
todas as migrações, possamos realmente inserir
um código que será visto como uma migração
para que, quando essa
migração for executada, automaticamente
colocados no banco de dados . Então é isso que queremos dar uma olhada rápida nesta lição. Agora, a maneira mais simples de
fazer a semeadura é fazer
isso a partir do método de
criação do modelo Em tudo isso, podemos
dizer ponto do construtor de modelos
e, em seguida, especificar uma entidade. Digamos que temos equipes, ligas,
partidas, treinadores Digamos que eu queira inserir
alguns treinadores no sistema. Eu vou dizer que o coach da entidade e esse coach da entidade tem dados, e então isso tem
dados que me permite especificar quantos
treinadores eu precisar Isso não é ci brass
, são parênteses. E então, nesses parênteses, eu começaria a dar a
ele novos Então, eu posso dizer novo treinador. Posso especificar o
ID desde o início. Vou usar alguns IDs que
sei que não entrarão em conflito com
os existentes. O nome ID 20 é igual a Eu usarei meu
nome nessa situação. E o ID da equipe. Bem, eu posso deixar tudo isso porque estou sentando na carruagem. Agora, isso traz outro ponto
importante. Se você tiver dados hierárquicos, precisará se
certificar de que está configurando de acordo com a ordem ou
o nível de dependência, da mesma forma que queremos
criar as tabelas com as dependências
da
mesma forma que precisamos
semear os dados Porque eu não posso esperar
colocar Trevor Williams, o técnico da equipe ID cinco, mas depois de tudo isso estou definindo a equipe com a identificação cinco Tudo bem? Então, deixe-me mostrar
exatamente o que quero dizer. Se eu disser equipe,
quero uma nova equipe, vou plantar
uma nova equipe e essa equipe
terá, digamos, ID 20 O nome da equipe é Trevor Williams Sample
team. Tudo bem. Não posso dizer a
esse treinador que o ID da equipe é o ID 20
porque a ordem em que defini esses comandos
iniciais é a ordem em que
a instrução
car será gerada. Portanto, não posso criar
treinador e inserir treinador com ID de equipe 20 quando o ID de
equipe 20 ainda não existe Portanto, tenho que me
certificar de manter meus pedidos de acordo com
os níveis de dependência Não, como eu disse, você pode
colocar quantas quiser. Então, eu tenho um novo treinador aqui, e então eu posso simplesmente separar quantos objetos do
novo treinador eu precisar. Então, se eu quisesse três treinadores
no sistema inicialmente, é
claro, os IDs podem entrar em conflito Então, vamos manter esse nome, amostra um e amostra dois. E então, para as equipes, bem, eu não posso ser
o treinador da mesma equipe
repetidamente. Porque conhecemos as restrições. Portanto, quaisquer restrições existentes
no banco de dados, é claro, governarão as limitações que você tem ao se sentar, certo? Você só quer estar
atento a tudo isso. Obviamente, mais uma vez, provavelmente
é quando o
sistema acabou de ser instalado. Então, estou usando os IDs 2021 e 22 porque já tenho equipes e treinadores no sistema.
Eu não quero entrar em conflito No entanto, em um sistema totalmente novo
e em um novo paradigma, você provavelmente
começaria com um, dois, três,
quatro como seus IDs, porque
esses são os IDs que você definitivamente deseja
antes de qualquer outra coisa Agora, se você fosse fazer a
semeadura de várias tabelas, veria que pode ficar muito complicado. Honestamente, não
gosto de ver tudo
isso na criação do modelo Isso é muito código. Eu quero mantê-lo um pouco mais limpo. Então, o que eu faço ou recomendo que você
faça nessa situação é extraí-los em classes de
configuração inicial. Então, o que eu costumo fazer é criar uma pasta e
vou fazer isso
no projeto de dados
próximo às migrações Então eu chamo isso de configurações, e então eu tenho outra pasta lá
porque pode haver vários tipos de configuração
que talvez queiramos fazer Vou chamar
isso de entidades. E, dentro disso, terei as diferentes classes de
configuração por tipo de entidade. Então, por exemplo, eu quero uma configuração
de CD de treinamento. Agora, nesta classe, que vou tornar pública, vou herdar da configuração do tipo de
entidade Então, vou pegar
essa referência e dizer que
é para o tipo de treinador. Em seguida, inclua tudo
o que estiver faltando. Então, para o tipo de
treinador, eu quero isso. Então, agora eu vou ter que
implementar essa interface, que me dá essa
configuração de método e um construtor local. Então, agora que eu tenho esse construtor, esse construtor basicamente se assemelha ao mesmo propósito desse objeto construtor de
modelos, certo? Então, posso dizer que tem dados. Vou considerar
essa parte como se fosse uma equipe, deixe-me pegar a parte que
tem dados. Vou cortar, vou apagar tudo isso
do contexto de DV E aqui, eu
quero dizer construtor, ponto e depois colocar tem dados. Então, tudo o que eu tinha tinha dados e muito mais se encaixa
perfeitamente nesse método. Portanto, o Builder dot tem dados
e, em seguida, você pode
inserir o máximo registros de visualização nessa classe dedicada. Agora, é claro, se estou migrando
para uma classe dedicada, preciso de uma maneira de fazer
referência a ela ou fazer referência
a ela no contexto do banco de dados. Então, de volta ao contexto do banco de dados, vou dizer model builder
dot, apply configuration
e, em seguida, new e apenas passar o nome desse
método, desculpe, essa nova classe que criamos, que é uma nova classe de
configuração. Então, eu apenas passo uma
nova instância disso, e pronto. Então, quantas
classes de configuração você criar, você só precisa
passar essas linhas. Mais uma vez, mantendo
essa ordem. Então eu fiz isso para assentos de ônibus
ou ônibus. Vamos fazer a mesma coisa com
as equipes, certo? Então, vou
jogar com preguiça aqui, copiar e
colar o arquivo existente
e mudar o nome para
sede da equipe, configuração E então eu vou atualizar
as referências no arquivo. Então, essa é uma
equipe de quatro tipos. Isso é para a equipe. E então nossa seção de
dados pessoais
virá diretamente disso. Vou apenas recortar e colar em seu arquivo de
configuração dedicado. E de volta ao contexto de DV, posso simplesmente duplicar
isso e dizer configuração inicial
da equipe,
e pronto Então, isso parece muito
mais limpo para mim e é tão eficaz quanto ter
tudo no arquivo. Mas é claro que esse
método se mantém um pouco mais kosher e fica um pouco melhor
quando fazemos assim Então, vamos dar uma
olhada no que obtemos quando
tentamos adicionar uma migração. E quando eu faço isso, eu chamo isso de
equipes e treinadores padrão adicionados Agora estou vendo que o construtor de
migração está fazendo
algo diferente. Nunca vimos
isso fazer isso antes. Portanto, é sempre criar
tabela ou alterar tabela. Agora, ele insere dados
nas equipes da tabela com essas
colunas com esses valores e está fazendo isso
para tudo. E mais uma vez,
essa ordem é importante. A See it cuidou
de todas as equipes. E então
cuidará de todos os treinadores
que dependem
das equipes, certo Então, imagine que, se eles
fossem misturados, tentaremos
inserir um treinador com
um ID de equipe 21 antes mesmo que
a equipe com ID 21 fosse
criada como receita para o desastre. Portanto, lembre-se de que o
pedido é importante. E no D, os dados de
exclusão estão apenas revertendo todas essas inserções com a instrução delete Então, se eu fizer uma atualização do banco de dados, vou receber esse
erro, certo? Estou recebendo esse erro
dizendo que tenho um conflito com a equipe
e a coluna de ID da liga. Tudo bem. Isso é bom. Então, nessa situação, eu tenho
que modificar o que está acontecendo com a equipe porque eu
não completei os dados, então você tem que estar ciente disso. Você precisa estar ciente
do fato de que suas restrições determinarão se os dados podem entrar Portanto, o ID da liga não pode ser nulo. Essa é uma restrição
que está no banco de dados. Uma equipe tem que estar em uma liga. Então, eu não posso sentar
equipes sem ligas. Então, vou
semear rapidamente uma liga de amostras. Então, seguindo os mesmos passos, vou encorajá-lo a fazer uma pausa e
experimentar
você mesmo Mas o que eu fiz foi
criar uma nova classe que estou chamando de configuração
inicial da liga, seguindo as mesmas
etapas herdadas configuração
do tipo de entidade do tipo liga E então estamos apenas construindo uma liga com o
ID 20, mais uma vez, para evitar conflitos
no banco de dados, e o nome é liga de amostra Em seguida, atualizo
retroativamente configuração inicial da
minha equipe para adicionar esse ID da liga a
cada uma dessas equipes
e, por extensão, ao contexto do
banco de dados em que
agora tenho a configuração da
semente da liga acontecendo antes de
tudo Agora, eu cometi um
erro, certo? Eu gerei essa migração
quando os dados estavam incompletos. Agora vemos que
essa migração está falhando. Como podemos reverter? Bem, o primeiro passo é
remover a migração. Então, isso sempre removerá
a migração mais recente. E então eu posso simplesmente ir em frente
e gerá-lo novamente. E desta vez, se
olharmos, vemos que primeiro está criando
a liga, depois criará as
equipes e depois os treinadores Então, vamos dar outra olhada
no banco de dados de atualização. E depois de níveis de registro
e de
sermos muito verbos, concluímos e sabemos
agora que temos esses dados Então, mais uma vez, isso agora
é uma migração. Portanto, espera-se que isso aconteça ao
longo da cadeia, desde a migração
inicial até
a última migração que você possa ter
para seu banco de dados. Portanto, pode haver
momentos em que você precise introduzir pesquisas e
tabelas diferentes ao longo do caminho e precise desses valores
como padrão desde Bem, isso é perfeito para isso. Basta adicionar
as configurações e depois
colocá-las no contexto do banco Portanto, o construtor do modelo
saberá que, ao fazer
minha construção, ao
criar o modelo, preciso estar ciente dessas
configurações de assentos
33. Migrações de volta: Ei, pessoal, bem-vindos de
volta nesta lição, vamos dar uma olhada em como
reverter e gerenciar
migrações em geral Então, fizemos
algumas atividades em que fizemos algumas alterações
em nosso banco de dados
e, a cada alteração, fizemos
uma migração e depois
atualizamos o banco de dados. Mas o que acontece quando você
faz uma migração que não quer
ou, em retrospectiva, quer revertê-la, fazer um ajuste e refazê-la Agora, neste exemplo, eu já fiz uma migração. Vou mostrar as alterações
que
fiz para acionar essa migração. Eu mudei o objeto do domínio base para ter esses quatro campos. E esses campos geralmente são
usados para fins de auditoria. Você sabe, quando você
tem pessoas inserindo dados em um banco de dados, você quer saber quando ele foi
criado, quando foi
modificado pela última vez , criado por
quem e modificado por quem. Agora, normalmente, você gostaria que
eles fossem meio claros. Então, eu deliberadamente os nomeio mal, só para mostrar que você é um
erro que provavelmente
justificaria uma correção, uma reversão ou
algo parecido justificaria uma correção, uma reversão ou reversão Então, nessa situação, se você apenas olhar
os nomes das colunas, eles não são realmente
muito coesos, certo Data de criação da última modificação. Se estou apenas vendo
esse nome, não
sei se essa
é a data da última modificação ou se foi a última
modificação feita por quem. Não sei se
essa modificação significa data de
modificação ou pessoa
que a modificou. Eu não sei. Você
entende o que estou dizendo. Então, essas são as coisas
que se, você sabe, se você é obsessivo
com esses detalhes
, essas coisas vão parecer
meio feias para No entanto, a questão é que eu
fiz esses ajustes
no objeto de domínio base,
que, obviamente,
está sendo herdado por todos os outros objetos de domínio Então, quando gerei
essa migração, que acabei de chamar de campos de auditoria
adicionados, você pode prosseguir e fazer isso para, você sabe,
trabalhar comigo. Mas quando fiz isso, você
percebeu que ele acabou de adicionar essas colunas a
cada tabela existente. No entanto, para cima e para baixo. E então eu fui em frente e
atualizei o banco de dados, o que foi uma operação
bem-sucedida. Então, a partir de agora, cada campo no banco de dados tem
essas colunas de auditoria. Agora, o que acontece quando eu não
estou mais
satisfeito com isso? Então,
já vimos que quando
geramos uma migração e percebemos que
talvez haja um erro nela, sempre
podemos remover
a migração. Mas veja o que acontece
quando eu tento remover o E se eu for até
o comando e disser, remover a migração, tudo é
compilado e é bem-sucedido Mas aí eu recebo esse
erro dizendo que a migração com esse nome já foi aplicada
ao banco de dados. Reverta-o e tente novamente Se ele tiver sido aplicado
a outros bancos de dados, considere reverter suas alterações Você vê tudo isso.
Em outras palavras, essa migração
já foi aplicada. Portanto, ele não pode simplesmente remover migração porque a remoção da
migração realmente exclui a referência ou o registro desse
arquivo de migração da pasta Portanto, é à
prova de falhas que dizem que
eu já anotei
essa alteração no banco de dados. Portanto, não posso simplesmente
excluir isso do histórico sem
que você
modifique o banco de dados Então é isso que
estamos aqui para fazer para entender como
lidamos com essa reversão E é um procedimento bem
simples. Não sei, talvez
essa mensagem pudesse ter nos dado
uma dica maior ou melhor de como
poderíamos reverter o banco de dados, mas vamos fazer isso juntos Então, reverter o
banco de dados é realmente uma
atividade de atualização do banco de dados, certo? Parece meio contraditório, mas trabalhe comigo aqui Então, para reverter o banco de dados para
um ponto anterior no tempo, o que precisamos fazer é executar nosso
comando de atualização de banco de dados e, na verdade, dizer a ele para
qual migração
queremos atualizar e, se estiver no passado, realmente reverter. Então, quero voltar
à migração que fiz, onde
adicionei as equipes
e treinadores padrão logo antes de adicionar os campos de auditoria Então, vou simplesmente
dobrar o arquivo muito lentamente, ou você
pode dizer, com razão, renomear, e vou
copiar o nome do arquivo Eu não preciso do CS. Eu só preciso do nome
porque esse é o nome
da migração que
está realmente armazenada,
aquele sublinhado do carimbo de data/hora e qualquer
palavreado Então, no console do gerenciador de pacotes, direi atualizar o banco de dados novamente. E então vou
passar o nome
da migração entre
aspas e pressionar enter, e então você verá que ela
realmente fez o que
estava pronto Tudo bem? Então, é só disso que falamos quando você está
pronto e tem que fazer. Então, os comandos que foram
executados agora foram para remover de
tudo o que estava lá. Está alterando e eliminando a
coluna modificada. Se você olhar na parte concluída,
bem, o arquivo de migração, desculpe, se você olhar na parte concluída desse arquivo
de migração, é tudo
que ele faz, ele pede que
ele solte as colunas. Então, esse é um
exemplo prático do que acontece uma reversão e duas quando essa descida realmente é
acionada, ela realmente desfaz
tudo o que a subida fez Então, agora que revertemos ou atualizamos o banco de dados
para uma versão anterior, posso realmente prosseguir agora e dizer com segurança remover a migração Ele fará isso de
boa vontade, de bom grado e sem dúvidas ou
escrúpulos, e pronto Ele removeu a migração
anterior. Vou apenas fazer
ajustes no meu com base no objeto principal. Lá vamos nós. Eu atualizei os nomes dessas
colunas para serem um pouco mais descritivos do
que estará nelas. Crie uma data, data de modificação, criada por, modificada por. Agora, depois de fazer tudo isso, vamos adicionar nossa migração
novamente e
adicionar a sensação de
auditoria de data. OK. E quando isso for feito,
eu só quero vejamos o que acontece
com nossa coluna de datas. Portanto, essas são colunas de data e hora
e não são anuláveis. O que acontece é
que quando você tem um
campo de data e hora anulável no banco de dados, ou ele precisa inserir um valor É por isso que obtemos esse valor
padrão em todos os lugares em que essa coluna
de data e hora será adicionada, certo? Portanto, não podemos ter nenhuma data
em um campo de data anulável. Então, está inserindo
essa data padrão, que no banco de dados, você provavelmente veria
cerca de 01010001 É apenas uma
data padrão, eu acho, desde o início
dos tempos. Tudo bem. Então, com tudo isso feito, podemos prosseguir e
atualizar nosso banco de dados. E vou executar esse comando sem
especificar nenhuma migração, e será uma operação
bem-sucedida Lá vamos nós. Então, agora, nosso banco de dados está equipado com , no nível mais básico,
alguns campos de auditoria Então, quando as pessoas estão entrando, é
claro, queremos saber quando elas
criaram esse registro? Quando foi modificado pela última vez, depois quem o criou
e quem o modificou pela última vez.
34. Manipulate de entradas antes de salvar as mudanças: Ei, pessoal, bem-vindos de
volta a esta lição. Veremos como podemos manipular as entradas
antes de salvar as alterações Agora, uma pequena explicação do motivo pelo qual você gostaria de fazer
algo assim seria talvez o
fato
de termos acabado de adicionar
campos de auditoria para todas as tabelas, certo? Então, acabamos de adicionar todos
os campos de auditoria no objeto de domínio base. E, evidentemente, isso é um pouco mais trabalhoso porque vimos que, quando
adicionamos dados, temos que formular
os objetos e depois
adicioná-los e adicioná-los ao contexto e
depois salvar
as Agora, isso significa que toda vez alguém adiciona uma
equipe, uma liga uma partida, um técnico
ou qualquer coisa ao banco de dados ou
o modifica,
colocamos uma
responsabilidade extra em nós mesmos ou em nossos
desenvolvedores de dizer: sempre coloque a data de criação, sempre colocando uma data de modificação, pelo
menos se você quiser que os
dados sejam padrão Agora, fazer isso em
um sistema maior
pode ser muito complicado porque estamos trabalhando apenas
com quatro tabelas, e eu já estou irritado
só de pensar nisso Imagine quando você tem 2030
ou mais tabelas lidando com. Então, neste momento, é bom entender
como o contexto realmente dá acesso a tudo o
que está prestes a ser salvo, e você pode realmente
manipular o que precisa manipular antes
de salvar as alterações Vou abordar
nosso contexto de dados aqui, e será uma
experiência muito interessante agora, porque podemos substituir as alterações
salvas, certo? Portanto, vemos algumas opções de salvar alterações
a serem substituídas Temos o padrão, que é quando chamamos as alterações de salvamento de pontos de
contexto. Nós podemos substituí-lo. E então podemos
realizar algumas operações aqui antes de dizermos
realmente salvar as alterações. Você notará aqui
que salvar as alterações realmente retorna um número inteiro, que geralmente é
mais de um quando o salvamento é bem-sucedido e menor que um ou zero
quando não foi bem-sucedido Portanto, se precisar, provavelmente
poderá incorporar
isso às suas verificações para ver se foi uma operação de
salvamento bem-sucedida ou não. Mas, por enquanto, não
vamos nos concentrar em saber como
podemos interceptar tudo o
que está prestes a ser salvo e manipular esses valores
antes que sejam salvos
no banco de antes que sejam salvos
no Há
algumas coisas que você deve
conhecer quando estiver
nessa área. Em primeiro lugar, há um objeto que nos é
dado chamado rastreador de
alterações Acho que
analisamos isso anteriormente, mas vamos ver
o que isso nos permite fazer. Então, mudamos o rastreador e, em seguida, podemos dizer entradas de pontos Na verdade, isso nos dá
a lista de entradas que entram nas alterações salvas e estão sendo rastreadas pelo
contexto na memória Posso dizer que as entradas de VR são iguais às entradas de pontos do
rastreador de alteração Ok. Outro recurso interessante
de poder ver as entradas é interrogar o que
chamamos de estado da entidade Então essa é uma enumeração dada a nós. Uma enumeração é apenas uma constante, e essa constante tem
estados diferentes que geralmente representam em que estado sua entrada estaria no momento em que
chegasse às alterações salvas Portanto, permanecemos inalterados. seja, talvez você tenha feito uma consulta, o rastreamento estava ativado,
então ele está rastreando, mas você não a atualizou, não fez nada com ela, então está em um estado inalterado Além disso, acho que isso é
autoexplicativo. Você está prestes a adicionar
algo ao banco de dados. Então, sempre que você cria
um objeto e diz contexto, ponto adiciona e
depois insere o objeto, ele agora está em um estado adicionado Desanexado significa que não está sendo rastreado pelo
contexto. Tudo bem? Modificado significa que,
bem,
você pegou , mudou alguma coisa nele, e então você disse, aqui está. Então, ou estava sendo
rastreado quando foi alterado. Agora, ele vê
que é diferente
do que estava
rastreando inicialmente, ou não estava sendo rastreado, e você chamou explicitamente context dot update
e o transmitiu E então, na verdade, há
outra maneira de atualizar,
basta marcá-la como modificada, certo? Então, na verdade, você pode
simplesmente colocá-lo
no estado de entidade modificado para que o rastreador saiba
que eu deveria estar rastreando isso
como um objeto modificado Excluído, autoexplicativo. Sempre que dizemos que o contexto
exclui e atribuímos a ele o objeto, ele agora está em um estado excluído Então, esses são realmente
os estados de entidade disponíveis para nós, certo? Mas então, em certas situações, talvez
precisemos rastrear
algumas e não rastrear algumas. Então, com as entradas, eu não quero ver
todas as entradas. Não preciso de
nada que não tenha sido modificado ou que não
tenha sido adicionado, pelo
menos para meus propósitos
de auditoria Agora, mais uma vez,
estou apenas lhe dando um conceito geral que você provavelmente
pode adotar por
diferentes motivos, certo? Portanto, você pode ter algum registro de auditoria
complexo ou um segundo banco de dados
no qual precise gravar registros. Talvez seja necessário rastrear, quando isso foi adicionado. Quando isso foi modificado? Se isso deve ser excluído
e gravado um armazenamento de dados separado,
seja o que for, o rastreador de alterações permite que você
intercepte essas entradas faça o que você precisa fazer
antes que as alterações salvas Então, vamos dar uma olhada nisso. O que queremos fazer é obter todas as entradas
que estão prestes a ser modificadas ou adicionadas e, em seguida,
atualizar as respectivas colunas Agora, vamos
nos concentrar apenas nas datas. Ok. Certo? E então podemos seguir em frente e salvar as
alterações depois. Então, eu posso estender esse enumerável porque essa função está apenas
retornando um enumerável, então eu posso simplesmente estender
isso e dizer onde,
e podemos usar Então, eu posso dizer onde Q ou
minha expressão Lambda, e então vou
procurar o estado é igual a, e então posso usar
esse número para filtrar adicionado ou Q é
equivalente ao estado da entidade
que acabei de adicionar, então isso agora seria modificado Aqui, estamos
filtrando e obtendo todas as entradas que estão prestes a ser adicionadas ou modificadas Ok. Em seguida, vou fazer com que quatro lóbulos de cada lóbulo
passem por essas entradas e as
convertam nos objetos do domínio base Então, dê uma olhada no
que está acontecendo aqui. Entrada nas entradas. Agora, se observarmos a entrada, entradas do tipo
entrada de entidade. Tudo bem? Então, quando estou convertendo, posso simplesmente converter a entrada, mas preciso converter a entidade do ponto
de entrada Portanto, a entrada tem alguns
objetos, algumas propriedades, você pode ver os
valores atuais no objeto, você pode ver os valores originais. Portanto, mesmo para fins de
registro de auditoria, você pode ver onde estavam
as
propriedades antes ou os valores nas
propriedades
antes e quais são
os valores agora. Você pode observar o contexto, e a entidade, é claro, incorpora o tipo de entidade real que o contexto conhece Agora, como usamos
o objeto de domínio base e todos os outros
tipos de entidades herdam disso, posso reduzi-lo a
esse nível para poder modificar os campos do objeto,
porque, neste
momento, não sei se estou salvando um time de futebol Não sei se estou
salvando uma partida. Não sei qual tipo de entidade está realmente
aparecendo na entrada. Estou apenas convertendo-o no objeto
do domínio base para que eu possa começar a interagir
com os campos Para cada um, vou dizer que objetos
auditáveis criam uma data, simples e simples é igual
a um ponto de
data e hora, porque estou
prestes a salvar as alterações.
É preciso saber que a
modificação, desculpe, foi feita Data modificada, é
a mesma hora. Mas então pense sobre isso. Estou procurando por itens
adicionados e modificados, mas toda vez
que algo é adicionado. Claro, eu quero
ter a data de criação, mas não quero ter
a data de criação toda vez que
algo é modificado. Você vê como isso é sensível. Então, estou analisando tanto os
adicionados quanto os modificados, mas estou inserindo
a data da modificação toda vez
que algo será modificado. Ou, desculpe, estou inserindo
a data de criação toda vez que algo está sendo
modificado, o que está errado. Tudo bem Eu vou
tirar esse. Então, toda vez que
clicamos em salvar alterações, quero dizer que foi
modificado porque é verdade. Se estava sendo criado
ou modificado, data de modificação é não. No entanto, eu só quero
definir a data de criação se o estado do ponto de entrada for equivalente ao ponto do estado da entidade criado ou adicionado, certo? Então, quando estiver em andamento, dirá
que, para esta entrada, definirei a data de modificação. Então, se está sendo criado
ou realmente sendo modificado, estamos definindo a data de modificação. No entanto, se estiver sendo adicionado, defina a data de criação. Caso contrário, ele simplesmente ignorará
isso. Não vai fazer nada. Vamos para a próxima entrada e faremos tudo isso
até que esteja pronto. Agora, quando toda essa
auditoria estiver concluída, a última coisa que queremos
fazer é finalmente salvar as alterações É como um último Hurrah. Quaisquer que sejam
os dados recebidos, não sabemos, não
sabemos qual é o tipo de conjunto de
banco de dados de entidades. Só sabemos que todos eles têm um objeto de domínio
base em comum. E uma vez que isso esteja pronto, podemos ir até
os campos de auditoria, independentemente do tipo de nível
superior, eu vou dizer, e depois fazer os ajustes e
depois salvar as alterações. Agora, antes de seguir em frente, acabei de notar que não
há referências
a esse método. No meu programa de CS, tirei o pó de alguns
dos métodos antigos que
teríamos usado, e cada um desses métodos
chama salvar alterações,
mas veja só, salve as alterações em uma sincronização No entanto, substituímos
apenas as alterações de salvamento. Esse é o
meu erro, certo? Portanto, o método de substituição que realmente
estamos
procurando é salvar as alterações Então, o que vou fazer é reescrever essa substituição porque acho que existem várias Só quero ter certeza de que
escolhemos a correta. Então, salvamos
as alterações, salvamos as alterações e salvamos as alterações, uma sincronização
que usa dois parâmetros
e, em seguida, essa que usa um parâmetro com um padrão. Então, acho que é
isso que
queremos , porque se
usarmos o outro, teremos que
fornecer um lingote
e, bem, esse
token de cancelamento está lá por padrão, mas queremos aquele
com o padrão, onde sabemos que não precisamos
fornecer nenhum parâmetro Vou usar esse e
apenas organizar meu código
aqui, certo? Lá vamos nós. Portanto, somos uma tarefa pública de substituição
em Salvar alteração é uma sincronização, e esse é o parâmetro Você pode prosseguir e
fazer esse ajuste
e, além disso,
precisamos fazer esse
syn porque, bem, é um syn, então precisamos
torná-lo um método assíncrono E então, se estiver
chamando um síncrono, é um método assíncrono, o
que significa que queremos usar
o método que significa que queremos usar assíncrono aqui também Eu posso simplesmente trocá-la para salvar mudanças em
um pecado e isso requer um peso. Então, eu posso simplesmente passar um
peso para isso, e deve ser isso. Então, eu tenho consistência. Vou usar o
mesmo
token de cancelamento no parâmetro
ali mesmo. Tudo bem Então, com esse ajuste, não, estou vendo todas as 12 referências sendo feitas às alterações salvas. Então está um pouco
melhor agora. Tudo bem Isso significa que, a partir do nosso program.cs, quando
chamarmos o contexto, ele realmente
atingirá nosso novo arquivo personalizado
e, em seguida,
fará tudo
isso antes de chamar a base. Tudo bem? Então esse é o poder de
superar tudo isso. Então, vamos dar uma olhada
nisso. Tudo bem E o que eu não indiquei quais métodos eu tirei o
pó, peço desculpas Então, estamos usando os métodos simples de operação de
inserção em que adicionamos novas ligas
e equipes com a liga, e eu estou fazendo a simples
atualização do registro da liga, estamos atualizando o
recorde da liga e o recorde da equipe. Então, dando uma olhada
no console e nas
instruções SQL que estão sendo geradas. Você verá aqui que
eu tenho P três, e estou obtendo esse
valor de data e hora ali mesmo, certo? E quando está sendo
inserido, data de criação, data de
modificação, P dois e
P três estão entrando. Assim, aqui está P one. Há P one, que
é a nossa data de criação. E então temos P dois sendo nulo porque isso
seria criado ou modificado por Então, vemos
que nossas datas estão entrando em nossa instrução SQL
corretamente, certo? Então, mais uma vez,
essa instrução SQL é gerada no momento em
que você salva as alterações. Agora, nós a sobrescrevemos para fazer algumas coisas adicionais
antes dessa declaração Q. Então, essa é uma boa maneira de
injetar sua própria lógica
e um pouco de consistência ou
limpeza ou qualquer coisa parecida
que você precise fazer antes que os dados sejam realmente
confirmados no banco de dados, então você sempre pode substituir os
métodos de contexto Agora, há uma maneira
de estender ainda mais
o contexto do banco de dados
para facilitar algumas coisas. Então, no contexto, queremos
colocar talvez modificado por, como um nome de usuário ou algo
a dizer, quem o modificou. Obviamente, não podemos fazer isso aqui porque não há
como eu passar uma string que represente
o nome do usuário como
ou como qualquer forma de valor aqui porque mudanças seguras estão
apenas procurando por isso. Então, o que podemos fazer é
estender nosso contexto para aceitar dados adicionais que o contexto padrão não aceitaria, e então podemos massagear os dados antes de
chamarmos o contexto base. Então, podemos ver isso mais tarde, e acho que será
uma atividade divertida. Ok.
35. Ampliando o DbContext: Ei, pessoal, bem-vindos de volta. Agora, na última vez que estivemos aqui, estávamos estendendo o contexto do RDB para lidar com um pouco de trabalho de auditoria Em outras palavras,
estendemos as alterações salvas ou as substituímos para poder massagear para poder massagear
nossos dados um pouco antes de salvá-los no Agora, vimos os benefícios
disso porque agora vemos que
estamos obtendo as datas de
auditoria para a data modificada e criada. No entanto, uma limitação
é que não conhecemos a pessoa que criou ou modificou o registro em nenhum
momento. Então, essa é uma
das limitações estamos simplesmente ignorando,
porque ainda estamos meio que confinados ao que
as mudanças de segurança padrão
nos reservam Não consigo substituir esse parâmetro. A conta
solicita um nome de usuário Então, para contexto ou
programa, dot says
representaria o aplicativo que
o usuário está usando, certo? Quando alguém está usando o
aplicativo web ou desktop
, adiciona um novo lead. Eu
gostaria de registrar quem fez isso. Quero o
nome de usuário do sistema. Eu não quero colocar a
responsabilidade deles sobre eles, o usuário, de
me dizer quem eles são. Quero saber quem
estava logado quando essa ação foi tomada
contra esse registro Portanto, seria bom se
eu pudesse passar
um nome de usuário para as alterações
salvas para que
pudéssemos usá-lo na
auditoria antes de salvar Então, com toda
essa limitação de que
entendemos a limitação e
o que queremos realizar, vou direto ao assunto. O que vamos fazer
é estender o contexto do banco para ter outra
citação de versão e citação
que assuma
a função de salvar alterações ou assuma a substituição
das alterações salvas e
depois as entregue Então, isso parece um pouco mais
complicado do que realmente é
e, na verdade, já comecei
o trabalho. Então, eu criei uma classe
totalmente nova, que eu criei diretamente
no mesmo projeto de dados do contexto de banco de dados original. Estou apenas chamando isso de contexto de banco de dados da
liga de futebol auditável, desculpe Agora, esse arquivo de contexto de auditoria do banco de dados da
liga de futebol é um resumo,
então não seria,
você sabe, instanciado
sozinho E ele herda do contexto
do banco de dados. O que vamos fazer é deixar dados original
ou
o contexto de banco de dados da liga
de futebol herdar
do nosso contexto de banco de dados
da liga de futebol Agora, a vantagem disso é
que, ao usar essa, obtemos todas as funcionalidades disponíveis na versão
auditável,
mas a versão auditável nos
permite um pouco mais de
flexibilidade porque
não estamos confinados ao contexto
real do banco de dados
e o substituímos Então, com tudo isso
dito e feito, vou cortar esse
método AC de salvar alterações do nosso contexto de banco de dados
da liga de futebol e colocá-lo
na versão abstrata, e vou fazer algumas
modificações neste momento. Primeiro, vou retirar
esse token de cancelamento porque realmente não
preciso retirá-lo esse token de cancelamento porque completamente,
e
vou permitir que ele chame a base de salvamento de alterações porque
esse é
o contexto do banco de dados, certo? Mas também vou estender
esse método para usar um
parâmetro de string chamado nome de usuário. Agora, o que isso está fazendo é
permitir que cada método de chamada saiba que deve passar um nome de usuário para
chamar esse método corretamente. E vou
remover essa substituição
porque não estamos
mais substituindo Só temos um método
chamado salvar alterações, que apenas chamará
a base. Portanto, é como uma extensão ou um método antes
do método real. Agora que temos esse parâmetro de
nome de usuário chegando, agora
posso dizer que o ponto do objeto
auditável neste
ponto seria modificado por, e então o modificado por
seria o nome do usuário E da mesma forma, o criado
por seria esse nome de usuário. Agora, zero referências.
Por que isso? Isso porque, em nosso programa, ele ainda está chamando as alterações de salvamento
padrão. Deixe-me encontrar um desses
métodos. Aí está. Ele ainda está chamando
save changes async, que é o padrão para
o contexto No entanto, se eu observar as
sobrecargas disponíveis para mim, verei que
há uma nova sobrecarga, que me permite passar
o nome de usuário dessa string Lá vamos nós. Assim, eu posso
passar um nome de usuário. Digamos apenas que um usuário de
gerenciamento de equipe de teste. Me desculpe. Estou apenas tentando ser explícito
o suficiente para que possamos ver na consulta
do banco de dados onde as alterações
salvas estão acontecendo Essa é uma atualização simples. Assim, podemos procurá-lo
ou testar o usuário atualizado. Deixe-me manter as coisas simples.
Teste o usuário da atualização. Esse disco. Nós não precisamos disso. Vou deixar este sem
nenhum nome de usuário. Isso está modificando a liga. Este
não terá um nome de usuário. Essa é a auditoria. Para que eu possa mudar nome da
minha liga. Então você
não precisa fazer isso. Você pode usar seus dados
antigos ou inserir seus próprios dados, mas tudo bem. Mas vou colocar
algumas substituições para testar a
auditoria de criação de usuário
e, em seguida, vou deixar essa
sem nenhum nome de usuário, Então, vou executar isso
neste momento e vamos ver
exatamente o que acontece. Então, quando estou vendo
algumas das declarações, vejo aqui nas
alterações salvas que eu tenho aquele usuário de
criação de auditoria de teste. Lá vamos nós. Então, esse
usuário de criação de auditoria de teste foi quem criou
essa liga de testes de auditoria. Tudo bem. Lá vamos nós. Então essa pessoa, esse usuário está entrando como P zero e P dois. E se olharmos P
zero é o criado por e P dois é o modificado por. Então é assim que podemos colocar
esses usuários no sistema. Observo que, embora eu possa ter
citado isso aqui, mais uma vez, em um aplicativo real
em que você tem pessoas fazendo login e assim por diante, existem maneiras de obter os nomes de usuário e simplesmente inseri-los
nas alterações salvas principais aplicativos.NET da Web, você pode até mesmo injetar o contexto CTP ao longo do caminho e renunciar Nos principais aplicativos.NET da Web,
você pode até mesmo injetar
o contexto CTP ao longo
do caminho e renunciar
a todo o processo de pegá-lo
e enviá-lo, mas Estou apenas tentando
mostrar como você pode estender seu contexto de banco de dados
e manipular seus dados maneiras cada vez mais criativas para
garantir que você tenha
essa integridade de dados quando eles chegarem
ao banco de dados. OK.
36. Implemente a auditoria completa de banco de dados: Tudo bem, pessoal. Então, da última vez que estivemos aqui, estávamos apenas percebendo como fazemos nossa auditoria. Tudo bem. Então, para saber que a auditoria é apenas uma data modificada e modificada através da criação do atendimento criado por. Mas então você pode ter outra necessidade onde você pode precisar auditar todo o rolo. Então você pode estar em um banco de dados separado ou é uma tabela separada, ou pelo menos isso é sempre feito tradicionalmente. Às vezes, o que as pessoas fazem é colocar gatilhos na tabela de modo que cada vez que algo é salvo, editado ou excluído, ele irá automaticamente escrever são necessários para outra tabela que é caminhão. O que a atividade aconteceu em uma tabela específica é tirar uma cópia da tabela. Então vamos pegar uma cópia dos valores originais antes da operação, os novos valores após
a operação, e serializá-los em uma string e armazená-lo dentro do banco de dados. Como pode ser lido. Isso depende do aplicativo e do desenvolvedor de cada vez. Mas eu estou apenas mostrando a vocês como EF Core é flexível em acessar dados antes e depois do fato e como podemos manipulá-lo durante. Então vamos começar criando uma nova classe e eu vou colocá-lo no domínio. Você provavelmente poderia colocá-lo em comum, mas realmente vai ser uma classe de domínio. Cria uma nova classe. Não quero chamar de auditoria de TI. Então auditoria vai ter alguns campos, vai ter o id padrão, uma string para o nome da tabela. Então tornamos isso público. E depois colocamos nos campos. Então ele vai ter ID nome da tabela, datetime, o que
significa que a hora, é claro que foi inserido, o valor da chave. Portanto, qualquer chave primária está fora do registro sendo auditado, os valores antigos do registro e os novos valores do registro. Então, depois de replicar essa classe de auditoria, você pode passar para o nosso contexto de banco de dados auditável. E nós vamos adicionar esse conjunto de banco de dados, certo? Então ele vai estar no contexto de banco de dados auditável. Você precisa de uma auditoria definida? E eu só estou chamando de auditorias. Então vamos entrar em mudanças enganadoras. E eu quero realmente fazer algumas coisas antes de salvar as alterações, porque antes de
salvarmos as alterações, precisamos tirar uma cópia dos dados que estão chegando, certo? Então, logo acima de onde temos nossas mudanças de caminhão e sabemos o que aconteceu e assim por diante. Vou ver antes de salvar as alterações, certo? Este método não existe, então eu vou apenas controlar ponto e gerar esse stub método. E lá vamos nós. Então isso vai retornar uma lista de outra classe que estou prestes a criar chamada entrada de auditoria. Então, se eu fizer Ponto de controle, Vamos ver o que Visual Studio pode fazer por nós. Ele diz que pode gerar um tipo chamado entrada de auditoria em seu próprio arquivo. Então vamos apenas ir em frente e criá-lo em seu próprio arquivo. Sem dano, sem falta. Salte para a entrada de auditoria. Então, uma auditoria será basicamente uma obstrução do que precisamos, certo? Então vamos resolver esta aula um pouco. Então eu vou dizer entrada de auditoria pública. Então isso é basicamente o construtor. E eu quero a entrada da entidade. Então sabemos o que é a entrada da entidade. Isto está vindo do EF Core. E vamos chamá-lo de entrada de entidade e com certeza. E então vamos usar esse construtor para inicializar nossa propriedade. Então eu posso controlar isso e dizer Criar entender propriedade chamada entrada de entidade. E faz isso para mim automaticamente, certo? Então eu vou ter outros campos que tipo de muito o que nós tivemos na auditoria, certo? Então eu vou ter o nome da tabela de string. Eu também vou ter bem, vales
antigos e novos valores e bem Key Vault é tudo sobre não é envolve o que eu vou mudar os tipos de dados desses. Então temos o nome da tabela, temos o valor da chave que realmente vai ser como um dicionário. Alguém para alterar o tipo de dados para dicionário de string e objeto. Então, se você nunca trabalhou com dicionários é como um par de valores-chave para que eu possa ser capaz de resolver JSON. E isso é o que é um dicionário. Uma string seria a chave e os objetos seriam os dados que estão indo ao lado da chave. Então o ponto de controle inclui isso. E eu vou inicializá-lo para que nunca se saiba. Então, basta pegar isso e c é igual a um novo dicionário de string, um objeto. E basicamente isso é tudo o que vamos fazer por valores antigos e novos valores. E nós fazemos as mesmas inicializações e você vê todo esse tipo de parece consistente e pouco mais assustador bala em breve você verá o que estamos procurando alcançar. A próxima linha será para propriedades temporárias. Então eu vou dizer uma lista pública de entrada de propriedade. Que também é de vir da biblioteca de entradas de
entidade de freeware tendências mudança rastreamento, certo? Assim, você vê uma lista de entrada de propriedade, propriedades
temporárias é igual a uma nova lista. Eu vou ter um método rápido que é apenas devolver nossa propriedade em vez devolver um booleano para ver
que tem propriedades temporárias. Então, logo explique o que propriedades de temperamento realmente significa ou será usado para. Mas então nós vamos ter outro método que vai realmente construir ou auditoria necessária em eu vou chamá-lo para auditoria. Tudo bem. Eu só teria que incluir qualquer namespace lá. Lá vamos nós para a auditoria. E então podemos começar a construir todas as funcionalidades. Então, quando falamos sobre a auditoria, estamos falando sobre construir a entidade real, seu registro. Portanto, var auditorias é igual a nova auditoria. Inicialize um novo objeto de auditorias de tipo. E então começaremos a preencher todos os campos da auditoria. Então eu posso usar este inicializador de objeto. E então eu posso dizer, ok, hora de sabermos que você é “Datetime Dot Nl”, certo? Então estes são os pontos do tempo. Não. Certo? Então nome da tabela, isso é fácil o suficiente e não deveria usar um ponto-e-vírgula, desculpas. Nome da tabela é igual ao nome da tabela proveniente do local. Tudo bem? Então temos os valores-chave, que seria uma serialização dos valores-chave chegando, certo? Então eu estou apenas vendo valores chave é igual a JSON converter, ver serializar ou objeto e valores chave, certo? Então, lembre-se que este é um dicionário. Então nós vamos ter a chave, que vai ser como ID. Nós vamos ter o valor é armazenado como um objeto, por isso é um ID string, ou no nosso caso estamos usando int ids. Seja o que for, só vai ter esse par de valor de chave e vamos apenas armazená-lo como JSON. E francamente, isso será a mesma coisa para os valores antigos e os novos valores. Mas há uma espécie de reviravolta com eles. Então nós vamos estar vendo algo como todos os valores é igual a todos os valores cones ponto sendo 0. Se for 0, então podemos armazenar nulo. Caso contrário, queremos converter o volume que vem do valor da chave aparecer. Saber a relevância disso. Se estamos fazendo certas operações, como inserir nosso registro, então não há nenhum valor antigo para esse registro porque é um novo registro. Então não há como obter os valores antigos. Então ele será log para ver se há quaisquer valores antigos a serem armazenados neste registro se não então nulo porque então podemos supor que era uma operação de adição. E então podemos ir em frente e serializar os valores se no caso de eu não ter comido ou uma atualização. Assim, da mesma forma que fizemos tudo da mesma forma, faremos novos valores. Então eu vou apenas duplicar esta linha e muda para dois novos valores. E onde quer que houvesse uma divisão, novos amigos. Portanto, se não houver novos valores, armazene nulo, embora os olhos armazenados nos novos valores. Acho que vou adicionar mais um campo e esse é o axônio. Então eu vou, na tabela de auditoria, adicionar
ações para que saibamos que tipo de operação estava sendo realizada, o que é certo. Então ação, e eu vou fazer o mesmo aqui, chamou-lhe ação. E então, a fim de auditar, eu vou dizer que a ação é igual à nossa ação local. Eu ouvi. Então sabemos o que estava acontecendo agora depois que construímos todo esse objeto de auditoria, esse método deveria estar retornando esse objeto de auditoria. Então, só devolvemos a auditoria. Isso é tudo para a nossa auditoria. Digite pelo menos para nulo à medida que
avançamos, podemos ver todos os ajustes que são necessários. Não, vamos voltar ao nosso contexto de banco de dados auditável. E para mim mais fácil, vou tirar tudo isso. Vou cortá-lo e vou colocá-lo dentro do nosso novo método. Então, antes de salvar as mudanças, essas são coisas que queríamos fazer de qualquer maneira, certo? Tudo bem, então eu vou refatorar isso um pouco em vez de tentar obter apenas essas entradas na quarta-feira, em vez de passar por um processo de eliminação. Então eu fui para ver se eles recebem as entradas do instrutor onde o estado não é igual a destacado e não é igual a em trapaceiros maneira seria capturar mais cenários no meio, certo? Então me dê as entradas que não foram destacadas ou inalteradas e, em seguida, esses são os interesses que estamos iterando através. Você vê aqui que está reclamando sobre o nome de usuário. Vamos ver o que controller.js para nós, podemos gerar uma propriedade que está bem. Ok, isso é só adicionar o parâmetro. usuário do perímetro gerado. Havia todos os tipos que eu estava procurando. Então agora temos o nome de usuário i, podemos Boston que nome de usuário antes, ver se muda e todos ficam felizes. Tudo bem, então em nenhum lugar recebendo todos os interesses não são tocados, não inalterados em nossas colunas de auditorias para eles. Agora, antes de entrarmos nisso para cada um, quero uma nova lista de entradas de auditorias e vamos compilar esta lista à medida que avançarmos. Então, para cada entrada, depois que ele passar por esses testes iniciais, eu vou tentar e ver que eu quero uma nova instância de política de entrada de auditoria nessa entrada vindo do nosso caminhoneiro. Certo. Então lembre-se que foi quando tivemos o construtor e auditoria para garantir que entrada Tolkien como seu parâmetro. Então eu vou obter o nome da tabela através de ver entrada de
auditoria nome da tabela ponto é igual a e, em seguida, você apenas se apressar e sentar que é igual a entry.metadata. Então eu só estou mostrando um monte de dados. Você pode realmente obter um barco, algo que é um parafuso para ser salvo no banco de dados. Posso obter os metadados, não a relação. Deixe-me ver o seu evento relacional precisa incluir referência ausente ou apenas soletrá-lo corretamente. Então ponto relacional ou, na verdade, acho que é um dotnet Core de três pontos um. Se core 3.1, aqui está, obter o nome da tabela. Lá vamos nós. Então, no tribunal dotnet Core 5, é ainda mais fácil obter um nome de tabela. Eu só vejo o nome da tabela GET. Tudo bem. E então vamos adicionar esta nova entrada de auditoria à nossa lista. Então eu só vou dizer Adicionar e auditar entrada como fato conjunto. Há outro campo que eu gostaria de sentar a partir de agora, e que seria a ação. Certo, então precisamos saber que ação está sendo levada a cabo. E então eu podia apenas ver o ponto de entrada, estado, ponto para cadeia, que é o leilão. Saiba que temos essa parte do caminho e deixe-nos focar nas propriedades. Então precisamos avaliar certas propriedades, uma, para copiar seus valores, sejam vales antigos ou novos pais ou a chave primária igual e remota. Esse é o nosso registro de auditoria, tem um campo específico para a chave primária. Então, o que podemos fazer facilmente é começar com um foreach e podemos dizer var propriedade na entrada, Propriedades do pensamento. Então isso é usar o que vamos chamar de reflexões e tudo o que é um
desses grandes subsídios é dado a nós por versões mais recentes de C afiado. Então podemos ver se a propriedade, desculpe, se a propriedade é temporária. Assim, isso nos permitiria avaliar se há mais bonito porão de valor dentro da propriedade. Então, quando mais novo, experimentando com a adição de registros e assim por diante, você veria que o valor do id tem um menos, eu acho que é int Min menos 2 bilhões e algo valor nele. Isso é, na verdade, um valor temporário até que o valor seja salvo. Certo. Então queremos ver se a propriedade é temporária do que pontos de auditoria. Entradas de auditoria são propriedades temporárias nesta propriedade. Tudo bem. Então isso é tudo o que podemos saber se isso vai ser adicionado ou não. Você verá mais tarde por que isso é tão importante. Então, depois disso, podemos continuar. Não precisamos fazer nenhuma outra operação nesta propriedade. Se é uma propriedade temporária, nós apenas adicionamos ao registro e então nós apenas continuamos. Não precisa se preocupar com isso. Nenhuma outra coisa que podemos precisar fazer se ele não está caindo nessa categoria é obter o nome da propriedade. Que mais uma vez, eu vou ter que apreender property.metadata e nós apenas usar a minha área de transferência nome de ponto de dados do ponto de dados da propriedade. Então eu estou recebendo inflamação e isso é o que os metadados são. Se o property.me for a chave primária. E isso é um método. Então, estamos vendo se estamos lidando com uma chave primária, então queremos armazenar os companheiros de chave. Então vai parecer parecido com o que fizemos aqui. Estamos sempre vendo a auditoria IS introduziu valores chave e, em seguida, obtemos o nome da propriedade como a chave ou o subscrito fora do IRI. E estamos armazenando o valor. Então nós vamos apenas ir em frente e armazenar isso. Então isso é tudo o que temos que o valor chave aparecer, certo? Então isso é string no dicionário, que é como um nome de propriedade. E então o valor ou o objeto seria o valor atual da chave primária. Então vamos para um interruptor onde vemos “Traga-me o estado de entradas”. Então mude o estado de entrada. E depois vamos tratar de alguns casos. Vamos verificar se ele está sendo adicionado, então precisamos armazenar os novos valores com o nome da propriedade no valor atual. Tudo bem? Embora foi se ele está sendo excluído, precisamos armazenar os valores antigos com o nome da propriedade e a origem de nós ECF valor atual e a origem do valor. valor atual é o que está sendo colocando saber e os valores originais, o que quer que fosse antes. Então isso vem a calhar saber quando estamos verificando se o estado NTT está em um estado modificado naquele ponto em que estamos vendo se ele não modificá-lo em uma propriedade foi modificado, certo. Então, estamos vendo se você alterar essa propriedade em particular que estamos olhando, então queremos saber qual era a propriedade original de Ardi e qual é o novo valor da propriedade. Tudo bem. Então é para isso que serve a instrução switch. E certo, não, é só por isso que estou fazendo. Então, mais uma vez, queremos armazenar se
é apropriado se for uma propriedade temporária, se for, isso significa
que é um registro que é um parafuso a ser adicionado e
não há chave primária porque isso está ligado antes de salvar as alterações. Então, nada está realmente acontecendo ainda. Formas de chave primária. No entanto, se ele faz chave primária que só estaria presente se ele estava em excluir ou uma modificação, então vamos em frente e fazer uma nota de qual é o valor da chave. Caso contrário, para o resto dos valores onde registrar quais são os novos valores, quais são os valores antigos, justo excluído, e ambos se estiver sendo modificado. Então, seguindo em frente, não, nós precisamos realmente salvar essas entradas de auditoria ou pelo menos construir uma lista de auditorias a serem peneiradas mais tarde, certo? Então eu vou fazer um para cada olho novamente, eu não quero salvar para cada entrada de auditoria em e eu vou obter essa lista entradas de auditoria ancoradas. E eu quero fora deles onde temos nossa expressão Lambda, q-dot tem propriedades temporárias. Podemos ver que é igual a cair como significa que não tem nenhum ou eu posso usar. Não estou dizendo que tenho feito isso para fins de legibilidade. Então, há propriedades temporárias nulas e eu não posso usar a entrada de auditoria aqui novamente, deixe-me apenas ver auditoria pendente auditoria para garantir que eu use essa entrada de auditoria pendente. Tudo bem. Assim, para cada entrada de auditoria pendente na lista que compilamos a este ponto onde existem propriedades temporárias nulas, então queremos adicioná-lo ao banco de dados auditorias sit para levar a lesão. Então ponto de entrada de auditoria pendente e, em seguida, aqui é por isso que tivemos que método de auditoria. Então lembre-se que os dois ruído de auditoria quando tomar qualquer valor foi Boston e o que foi sentar aqui e realmente criar em auditorias registro para retorno. Certo? Então estamos vendo tudo o que acabamos de compilar, todos os pares de valor de chave. Assim por diante, converte-o em um registro de auditoria real e ferramenta de edição ou banco de dados sit. Depois de tudo isso, eu quero retornar as entradas de auditoria que não têm ou desculpe que dual tem propriedades pendentes, propriedades temporárias. Então eu quero voltar onde eles têm propriedades pendentes. E é claro que somos nós para ser uma lista porque eu preciso que as células retornem uma lista. Lá vamos nós. Então é isso que está acontecendo antes de salvar as alterações. Ainda estou entendendo isso, Aaron. Eu acho que é porque eu fiz isso está dentro deste para cada um e esse é o cartão dele. Então isso deve acontecer fora do que para cada um eu peço desculpas. Então deixe-me chamá-lo rápido. E no final do método, passamos por auditorias compiladas e retornamos as que são temporárias. Lá vamos nós. Todo mundo está feliz com isso. Não, já fizemos isso antes. Salvando alterações. Tudo bem. E então vamos em frente e salvamos as alterações. Agora, o que vai acontecer depois de salvarmos as alterações com frequência
neste ponto é que vamos
ter todos os interesses de auditoria que tiveram os valores que ele quer que sejam adicionados onde eles ainda não tinham um ID. Eles ainda estão armazenados dentro deste nulo. Eu quero voltar e atualizar o ID válido saber que eles foram armazenados. Então, em vez de retornar a esses pontos, eu vou colocar isso em uma variável. Eu só vou chamá-lo. Resultado ou resultado. Então, estamos apenas armazenando o que isso seria, certo? E então nós vamos ter outro método que eu vou
chamar depois de salvar alterações em onde política nas entradas de auditoria. Certo. Então, obtemos as entradas de auditoria que estavam em um estado de ID temporário. Vemos que g e g é e tudo o que eles foram atualizados. Agora precisamos fazer algo após as alterações de salvamento. Então eu vou colapsar o antes e eu vou apenas gerar este método. E com isso feito, o que vamos fazer é passar pelas entradas de auditoria e verificar o que precisa acontecer, certo? Na verdade, isso pode nem precisar acontecer. Então eu vou dizer se as entradas de auditoria não é igual a nulo, por qualquer motivo, pode ser nulo. Ou lesões de auditoria cones ponto é realmente maior do que 0, significa que na verdade temos coisas para processar depois. Então você pode chamar esse método. Tudo bem? Então, dentro do método, o que precisamos fazer é passar porque neste ponto estamos assumindo que algo está dentro das entradas de auditoria, você só chegaria aqui. Se algo foi, então o que vamos fazer é avaliar cada entrada de auditoria e definir esta lista. E então nós estamos recebendo as propriedades em cada um desses, então dois para cada um listado para cada um. Então eu vou dizer para me pegar cada adereço em propriedades temporárias de ponto de entrada de
auditoria. Então lembre-se que compilamos uma lista de todas as propriedades temporárias. Então eu fui ter uma instrução if para ver se a propriedade é a nossa chave primária,
em seguida, adicionamos o valor da chave para ser o valor atual. Tudo bem. Então, estamos fazendo apenas uma rápida atualização desse valor de entradas de auditoria para ser o valor atual. Caso contrário, o novo valor é o nosso valor atual. Então, estamos apenas vendo se é uma chave primária, o que é mais do que provável porque ela acabaria sendo temporária. Se algo estava sendo adicionado, atualizado para o volume atual, saiba que tudo foi salvo. Caso contrário, se não fosse a nossa chave primária, que enquanto eu me sento lá posso pensar em um cenário onde você teria um valor de madeira para XOM. Essa não é a chave primária. Mas nesse caso, ainda o
atualizamos. Sem problema. Tudo bem, então depois disso, fazemos o para cada um, para cada um que estamos economizando, que definitivamente vamos adicioná-lo à auditoria. Só eu chamo nós adicionamos a auditoria interessada no antes de salvar as alterações. Então nós apenas auditorias dot add sob a auditoria dois para que ele possa ser convertido. Em seguida, retornamos um salvar alterações. Então, temos que chamar um mar de mudanças nesse ponto. Tudo bem. Agora, depois de salvarmos essas alterações, podemos retornar resultado aqui ou salvar resultados em vez disso. Então isso é realmente o que eu implementei para auditoria em vários aplicativos. E funciona muito bem porque, como eu disse, é realmente apenas armazenar representações de cadeia de caracteres de como seria o registro inteiro. E temos os valores antigos e os novos valores para uma comparação lado a lado. Assim, em uma interface de usuário que você poderia facilmente imprimir resultado porque é JSON, ele pode não ser facilmente legível por humanos. Então você pode querer ajustá-lo um pouco para que os detalhes apresentassem um B, ele é mais legível, mas pelo menos você pode ver tudo o que está acontecendo. Mantenha um registro de tudo o que está sendo excluído, modificado, ou adicionado aplicação garganta, o que quer que eles são vales onde naquele momento. Então ele pode ir em frente e fazer alguns testes, fazer alguns protistas, e olhar naquele estábulo de auditoria, é claro, você sabe ,
com todas essas mudanças, nós temos que brigar auto nova tabela. Então, se a migração de anúncios e dizemos tabela de auditoria adicionado. E depois de obter essa migração, temos que ver os dados são. E com tudo isso feito, você pode ir em frente e testá-lo e me dizer como funciona para você.
37. ATUALIZAÇÃO: Implemente a auditoria completa de banco de dados — correção: Pessoal, esta é uma solução rápida para o nosso vídeo anterior. Você teria configurado a auditoria e a auditoria completa do banco de dados. E vamos ver como ele serializa tudo para JSON, armazena-o no banco de dados. No entanto, se você tentar fazer várias operações, mas para empurrar, você pode encontrar uma situação difícil em que ele se queixa de uma digitação
para um campo de auditoria ou um registro de auditoria quando isso realmente não deveria estar acontecendo. E eu só estou aqui para mostrar a você o conserto para isso. Então, em nossa antes de salvar alterações ou salvar alterações, o que deve acontecer é que isso deve filtrar qualquer coisa que está inalterado já tocado para saber que sabemos que o estado da entidade, eu aposto Então qualquer coisa ser inserida vai obter o adicionado. E então sabemos que temos o estado da entidade para excluído e modificado ou assim. Mas então a razão pela qual estamos excluindo esses dois é que nós não precisamos auditar nada que é destacado, o que
significa que não está sendo levado, nosso não deve ser rastreado ou inalterado, ou
seja, bem, nada aconteceu. Então leia essencialmente o que acontece é que uma vez que o Salvar alterações é realmente chamado, o que estava sendo rastreado automaticamente vai para um estado onchange. Então, se você fizer várias operações, então você vai acabar com entradas de auditoria que estão sendo salvas. E então você vai e tenta dizer algo mais na estrutura ainda está rastreando os objetos antigos que foram salvos mais recentemente, incluindo o registro de auditoria. Então é por isso que ele precisa ser
filtrado neste momento porque ele está conhecendo um estado onchange. No entanto, por qualquer razão este filtro não está realmente funcionando como eu teria gostado que o talvez trabalhando para você, Amy anatta deste programa, isso é bom. Mas eu vi esse problema acontecer mais de uma vez. Então eu só vou te mostrar essa correção para isso. E é menos uma solução sofisticada. Tudo o que vou fazer é inverter a condição e isso funciona melhor para alguns. Então o que vamos fazer é dizer, dê-me as entradas onde sabemos que queremos experimentá-las, significando que o estado é equivalente a morto, ou é ferramenta equivalente modificada. E depois mais um. Ou é equivalente a esses BreakLine excluído. Certo? Porque sabemos que queremos rastreá-los. Não queremos rastrear os outros dois. Mas quando estamos tentando excluí-los por qualquer motivo, a exclusão pode não funcionar como deveria. Então, tudo bem. Nós só vamos trabalhar o nosso próprio que ainda mantém a qualidade e a integridade do nosso código. Não estamos vendo nos dar aqueles que sabemos que definitivamente queremos auditar. Então, estamos recebendo essas entradas e, em seguida, tudo o resto iria cair na linha porque há eles têm ou
declaração caso com base em qual estado é que precisa ser adicionado à entrada de auditoria. Então isso é uma solução rápida. Se teve essa dificuldade, podemos fazer isso e tenho certeza que terá uma experiência melhor. E se não, é claro, continuaremos a investigar e a olhar porque estamos todos aprendendo vermelho. Esta é uma biblioteca muito complexa e estamos fazendo o nosso melhor para tirar o melhor proveito dela.
38. Validação de dados com anotações de dados: Ei, pessoal, bem-vindos
de volta. Nesta lição, veremos como colocar
restrições e limitações, regras
gerais sobre as propriedades e os valores que
elas podem ter Agora, eu teria usado a
palavra restrição mais de uma vez. E isso teria sido mais específico para as migrações em
que vimos que restrições estavam
sendo adicionadas para relacionamentos de chave
estrangeira ou
para relacionamentos de chave
estrangeira ou exclusividade Mas essas são
todas migrações baseadas em algumas das regras
que estamos configurando em nossa criação de modelo
e com base nos tipos de dados e
no que definimos como
referência de chave estrangeira e tal Agora, além dessas situações
específicas, há momentos em que
você quer ser um pouco mais calculado e ter uma compreensão mais prática do que está sendo armazenado e
como está sendo Então, um exemplo prático. Quando analisamos a equipe, vemos que temos
uma string para o nome, que é traduzida em
um RCR no banco de dados, mas depois é VRTR Nós realmente queremos VRTRmx como nome
de equipe, certo? Então, aí mesmo, estamos abrindo o banco de dados para a
possibilidade de alguém colocar um ensaio inteiro nesse campo e chamar
isso de nome de equipe. Não queremos necessariamente isso. Outras restrições podem
incluir valores padrão. Então, adicionamos esses objetos
de domínio base. E eu estou apenas usando
este exemplo em que temos a data e hora Mas também pode
haver situações em que você queira valores padrão
nessas propriedades. Portanto, se um valor não for fornecido pela interface
ou pelo usuário, você ainda
deseja que ele tenha um valor. Vamos dar uma
olhada em como limitar parte do que nossas colunas de string
podem suportar, por exemplo Então, a partir do contexto de DV, e isso está usando uma API fluente. Portanto, teríamos analisado a API
fluente anteriormente, quando
especificávamos certas regras o que cada
entidade pode ter Todas essas linhas
de código ou blocos de código são realmente fluentes
com base em uma API fluente. Então, o que estamos fazendo agora é usar uma API
fluente para alguma validação Então, eu quero dizer
Model Builder Dot, e então ele
estará em equipe desta vez. Então, vou
dizer propriedade de ponto, que então se abre para
outra expressão Lambda Vou usar P como meus tokens. Eu vou dizer P dot, e então eu posso escolher a
propriedade em que estou interessado. Então eu disse nome. E depois disso, posso
dizer quais restrições ela tem. Portanto, posso dizer ao banco de dados
que é obrigatório ou tem um tipo de
coluna específico. E se eu não
quisesse necessariamente que fosse VT? E se eu quisesse que fosse TV. Por exemplo. E se eu
quiser definir um comprimento máximo, que é o que estamos prestes a fazer. Então, vou dizer comprimento máximo
e, em seguida, tudo o que ele precisa
é de um valor inteiro Eu vou dizer que nenhuma equipe
deve ter um nome com
mais de 25 caracteres.
Eu acho que isso é razoável. Existem algumas equipes com nomes
longos, como Barça, Munch e Gladbach, na Bundesliga Mas acho que 25 é
suficiente ou vamos aumentar para 50 para ficar
do lado extremamente seguro Portanto, nenhuma equipe deve ter
um nome que exceda 50. Agora, seguindo a
regra, isso realmente
configura a restrição
para uma propriedade, e é praticamente
uma propriedade por vez Mas eu posso fazer isso para
várias entidades. Então, eu quero essa mesma
restrição em uma liga. Não quero que nenhum nome de
uma liga seja um ensaio, e não quero que o nome de um treinador seja muito
longo. Tudo bem? Outras coisas que eu poderia fazer, eu poderia configurar essa
propriedade como um índice. Quando falamos sobre índices, eles são realmente pontos de busca de alta
velocidade Vou remover, acabei de duplicar essa linha
e, em vez de
dizer propriedade do ponto, vou dizer que o ponto tem índice E então isso
agora vai me
pedir uma expressão Lambda Então, vou
usar H como estamos fazendo índice e vou dizer que
o índice está no nome. Isso significa que, se
pesquisarmos pelo nome
, deve ser em alta velocidade. Aponte para os dados, que a consulta seja executada de forma
relativamente rápida. Na verdade, posso
fazer a mesma coisa pela nossa liga e
pelo nosso treinador. Observe que o que estou fazendo
é apenas copiar,
colar e substituir
os nomes adequadamente, porque todos eles têm estruturas
semelhantes Tudo o que
você provavelmente deseja
fazer seria especificar que essas colunas devem ser exclusivas ou qualquer valor que esteja
nelas deve ser exclusivo. Então, um estudo de caso para isso, bem, você não gostaria de duas
equipes com o mesmo nome, embora seja muito provável Você não gostaria de duas
ligas com o mesmo nome, embora isso seja, eu
acho, menos provável Mas em um
ambiente mais prático, se você estiver criando
um banco de dados para um sistema
de gestão escolar ou um livro, Storage. Você tem o ISBN, que é um
número exclusivo para cada livro, ou tem um número de identificação de
estudante, que é diferente do ID incrementado
padrão, mas apenas aquele ID que
eles usam na escola, você tem esse número de identificação gostaria de especificar
que ele é Então, eu poderia realmente estender
o índice has para dizer que esse índice
também deve ser único. Tudo bem? E
há outras coisas que você pode aplicar. Sinceramente, eu nunca usei alguns deles. Nunca tive uma
situação em que precisasse usá-los, mas sou só eu que você pode
explorar e encontrar uso para eles. Então, aqui, estou dizendo ao
banco de dados que essa é uma área de pesquisa de alta velocidade na equipe da tabela
e é única. Se você deseja ter um
índice em várias colunas
, você pode
simplesmente encadeá-lo. Assim, posso criar um tipo de objeto
anônimo. Analisamos isso anteriormente, então posso dizer que no
Lambda, vamos usar o coach Eu vou dizer que o
índice na tabela de treinadores é uma combinação ou tanto o nome quanto o ID da equipe deveriam
ser índices, certo? Assim, posso começar minha expressão
Lambda,
digamos, novas chaves abertas, para que ele saiba que
é um tipo de objeto E então, dentro desse objeto, basta especificar várias colunas, nome do ponto
H, ponto H. ID da equipe, vírgula, separação,
etc., etc., e então, por extensão, posso tornar tudo isso único Isso significa que a combinação
deve ser sempre única. Então, é mais como criar uma chave
composta nesse ponto. Tudo bem? Então, eu só estou te
mostrando alguns pedacinhos Não sei o quão
práticos eles são necessariamente nessa situação
específica, mas você pode ter esses desafios
ao projetar seu banco de dados
e, se você vem de um histórico
restrito de banco de dados
, sabe como é fácil. Ou é relativamente
simples
fazer isso no SQL Server
Management Studio No entanto, na
situação em que você está lidando com um banco de dados que
prioriza o código ,
gostaríamos de gerenciar todas as alterações
de
nossa estrutura de entidades
e permitir que elas cheguem ao banco de dados em vez
de serem misturadas e combinadas Então, quando eu fizer
todas essas alterações, se eu for até o console do gerenciador de
pacotes e adicionar uma nova migração, direi validações
adicionadas e sempre me lembro de
selecionar o projeto correto Então, eu acabei de mudar do console
para os dados, desculpas. Mas agora, quando analisamos
nossas declarações alternativas. Você vê aqui
o nome em equipes, agora
é VRCR 50, e o tipo antigo é
NVCR Max. Tudo bem? Portanto, existem muitas inibições
de
desempenho, que podem ocorrer simplesmente
deixando seus
tipos de dados como VRTA Max Então, quando você começa a colocar
essas restrições, na verdade está tornando seu
banco de dados mais compacto, mais eficiente e eficiente, apenas evitando o
estresse de, você sabe, considerações de
design futuras Então, temos a
coluna alter para os nomes. Então, cada um é gerado bem, então temos o índice de criação Então, vemos aqui, criar um
índice no nome da equipe, e ele deve ser exclusivo. E então criamos um índice o nome das ligas, que não
especificamos como exclusivo e criamos um índice na
tabela de treinadores, e as colunas são
nome e ID da equipe, e examinamos esse código de
filtro anteriormente Então, vou continuar
atualizando o banco e não prevejo
nenhum problema com a execução desse comando. E lá vamos nós. Temos uma linha vermelha, certo? Vamos ver o que é essa linha vermelha. Portanto, está dizendo que a criação declaração de índice
exclusiva foi encerrada porque uma
chave duplicada foi encontrada Então, estamos vendo
que já temos dados na tabela de equipes
e estamos tentando dizer que, para criar esse índice exclusivo na coluna
do nome da equipe, ele deve ser exclusivo. Então você pode ver minha
equipe estável aqui, eu tenho muitas coisas repetindo e repetindo Mas também está claro
que não posso dizer que a coluna de nome deva
ser exclusiva quando tenho um CMLN tantas
vezes no Tudo bem? Então, vemos que
a restrição funciona Vou deletar tudo o que
não está entre os três primeiros. Vamos ver se eu recebo
algum outro erro. Sim, eu previ que
obteria alguma chave estrangeira. Deixe-me limpar isso. Tudo bem. Então, para limpar isso,
tive que ir até os treinadores, certificar de que
ninguém estava treinando nenhum desses registros que
eu deveria excluir Também acesse as correspondências e
certifique-se de que nenhum
dos registros que eu deveria
excluir tivesse correspondências. Então, esse é um exemplo
prático de nossas restrições na
operação, certo Porque definimos a integridade
referencial para não ser em cascata,
mas para restringir Então, essas coisas simplesmente não podem acontecer quando essas
restrições estão inseridas, e estamos aprendendo
como
aplicá-las usando o EF Core. Tudo bem. Então, com tudo isso resolvido, vamos voltar e tentar atualizar
nosso banco de dados novamente. E desta vez, acredito que
teremos sucesso, e pronto.
Feito. Tudo bem. Então é assim que você pode configurar
a validação suas tabelas usando o FCR. OK.
39. Usando totalmente os arquivos de configuração: Ei pessoal, Nesta lição nós vamos apenas fazer um pouco de refatoração e começar a entender todo o poder de nossos arquivos de configuração um pouco mais. Então, quando fizemos nossos arquivos de configuração, foram realmente projetados com a intenção de facilitar nossas configurações de sementes. Então nós os nomeamos configuração de sementes da liga. Bem, a realidade da questão é que toda essa classe pode ser usada para todas as configurações relativas aos objetos de domínio de destino. Então, em outras palavras, apenas que eu chamo no contexto DB, nós realmente temos configurações relacionadas ao League. Já temos essa classe de configuração da liga. Nós podemos realmente colocar todo esse código dentro dessa classe para manter
ainda mais todo o nosso contexto de banco de dados meio limpo. Tudo bem, então vamos acabar com um monte desses blocos de configurações e o loop. Quantas tabelas você pode ter muitas configurações. Você quer tipo de manter tudo em troncos para que você possa vê-los ou encontrá-los muito facilmente quando você precisa. Então comece refatorando nossa equipe. Então, de repente, primeiro, vamos começar com equipes. Então vemos aqui que temos esta configuração para a equipe, esta configuração, temos dois outros aqui. E então temos toda essa configuração com a semeadura. Então, primeira ordem de negócios, eu vou renomear isso de configuração de sementes de equipes para apenas configuração de equipe. E vou deixar que refatore todas as referências, jogue o código. Próximo. O que eu vou fazer é trazer todas essas configurações do contexto de banco de dados. Então eu tenho ModelBuilder dot n TTT mapa, tudo isso. Eu queria cortar isso. E eu vou chegar a essa configuração de semente, o que vamos renomear o arquivo e o sobrinho, não se preocupe com isso, mas certo, não, eu só queria passar sobre a configuração. Então este é o construtor tem configuração de dados. Eu vou para baixo que ainda está no método de configuração. Tudo bem, e então eu vou colar todas as configurações que eu acabei de colocar. Em seguida, você verá um erro aparecendo com o ModelBuilder. E isso porque não temos nada chamado ModelBuilder neste arquivo. No entanto, se você olhar de perto, ModelBuilder é como uma versão genérica em nossa implementação Isso me permite dizer ModelBuilder entidade ponto e, em seguida, implicar a entidade. Nosso objeto construtor neste tipo é específico. É construtor de tipo de entidade para a entidade específica. Então todo esse tipo de implementação incorpora toda essa linha. Tudo bem, então todos esses conjuntos como entidade de pontos ModelBuilder, essa equipe, eu posso substituir isso por construtor. E construtor sabe que é relativo à equipe. Então tudo o que fazemos aqui é relativo à equipe. Tudo bem, então eu posso apenas dizer construtor ponto Tasmânia e então apenas listar todas as regras. Substitua isso também pelo construtor, apenas movendo-o para cima para que possamos ver onde ele começa e pára. E então eu vou continuar com os outros pedaços de configuração para a equipe, alguém para cortar isso e depois foi colocá-lo bem ali. E mais uma vez, eu vou apenas usar construtor para substituir que model.py na entidade ponto ModelBuilder, essas coisas de equipe. E lá vamos nós. Tudo bem, e então essa é a nossa configuração. Então nós já temos essa configuração sendo chamada bem aqui. Então, uma vez que ele atinge esta linha vai saltar placas ou o arquivo de configuração e ver tudo o que precisa ser feito para uma equipe. Então eu não posso realmente mover essas configurações acima do tem o eta. Então deixe-me apenas renomear este arquivo rapidamente antes que eu esqueça. E então vamos fazer a mesma coisa para os outros arquivos de configuração. Então, a configuração de sementes da liga, não
é mais específica para a semeadura. Então eu vou apenas ir em frente e renomear isso. Seus amigos vão em frente e renomear o arquivo, e então eu posso trazer mais configurações relacionadas a liga diretamente para o nosso construtor. Vá em frente e substitua o que preciso para substituir. E então eu fui em frente e fiz isso também para o treinador. Então você pode fazer isso, saber que você tem a essência. E, no final do dia, vemos contextos RDB parecendo muito mais limpos. E, em seguida, todas as coisas de configuração confusas lá em lugares específicos, seja de propriedade ou projeto.