Mergulho profundo com estrutura de entidade Core 5 | Trevoir Williams | Skillshare

Velocidade de reprodução


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Mergulho profundo com estrutura de entidade Core 5

teacher avatar Trevoir Williams, Jamaican Software Engineer

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Aulas neste curso

    • 1.

      Apresentação

      3:29

    • 2.

      Ambiente de desenvolvimento de configuração

      3:53

    • 3.

      Como configurar a solução

      3:59

    • 4.

      Como criar modelos de dados com EF Core

      8:11

    • 5.

      Como especificar o provedor de dados e a cadeia de conexão

      9:18

    • 6.

      Migrações e criação de banco de dados

      14:33

    • 7.

      Como criar scripts de migração

      2:10

    • 8.

      Banco de dados existente

      10:24

    • 9.

      Exibir diagrama com ferramentas principais do Entity Framework

      4:18

    • 10.

      Como adicionar registro de verbo à carga de trabalho do EF Core

      5:02

    • 11.

      Operações de inserção

      20:33

    • 12.

      Operações simples

      7:51

    • 13.

      Como filtrar registros

      12:51

    • 14.

      Métodos de execução

      10:26

    • 15.

      Sintaxe LINQ

      6:16

    • 16.

      Consulta de atualização simples

      13:33

    • 17.

      Consulta simples

      8:23

    • 18.

      Como rastrear Vs. Sem rastreamento

      7:53

    • 19.

      Revise relacionamentos de um para muitos

      7:44

    • 20.

      Como adicionar relacionamentos muitos

      17:26

    • 21.

      Como adicionar relacionamentos individuais

      6:35

    • 22.

      Como criar novo diagrama de entidades

      1:37

    • 23.

      Como inserir dados relacionados

      10:52

    • 24.

      (Carregamento de ansiedade) incluindo dados relacionados

      20:53

    • 25.

      Projeções e tipos de dados anônimos

      13:50

    • 26.

      Como filtrar em registros relacionados

      3:17

    • 27.

      Como adicionar vistas e outros objetos de dados

      5:31

    • 28.

      Como consultar entidades sem chaves (como vistas)

      6:02

    • 29.

      Como consultar com SQL cru

      8:02

    • 30.

      Adicionar e consultar usando procedimentos armazenados

      4:47

    • 31.

      Como executar SQL cru não consulta

      4:51

    • 32.

      Dados de semeadura

      12:16

    • 33.

      Migrações para trás

      7:28

    • 34.

      Manipule entradas antes de salvar mudanças

      14:28

    • 35.

      Como estender o texto DbContext

      7:04

    • 36.

      Como implementar auditoria de banco de dados

      25:18

    • 37.

      ATUALIZAÇÃO: Implementar auditoria completa - correção

      3:26

    • 38.

      Validação de dados com anotações de dados

      10:25

    • 39.

      Como usar arquivos de configuração

      4:36

  • --
  • Nível iniciante
  • Nível intermediário
  • Nível avançado
  • Todos os níveis

Gerado pela comunidade

O nível é determinado pela opinião da maioria dos estudantes que avaliaram este curso. Mostramos a recomendação do professor até que sejam coletadas as respostas de pelo menos 5 estudantes.

80

Estudantes

--

Projeto

Sobre este curso

Visão geral

Neste curso, Deep Dive With Entity Framework Core 5, você vai aprender a trabalhar com dados em seu . Aplicativos NET.

Na maioria das vezes em que o curso é criado para . Tecnologias NET, detalhes do Entity Framework e seu poder são negligenciados. Nós nos distraímos com abstrações e camadas e não nos focamos no que o Entity Framework está fazendo e pode fazer.

Neste curso, vamos rever os benefícios gerais de usar Entity Framework Core 5, que é o principal Mapper de relacionamento de objetos da Microsoft (ORM), para aliviar muitas preocupações e desafios que vêm com este componente do desenvolvimento de software. Também vamos gastar tempo descobrindo como traduzir aulas e referências para Modelos e Relacionamentos de banco de dados.

Vamos aprender como escrever consultas, atualizar bancos de dados em incremento, alterações de reversão e explorar os inúmeros recursos que o Entity Framework Core nos oferece.

Quando terminar este curso, você terá as habilidades e conhecimento do Entity Framework Core necessárias para interagir com dados e escrever problemas para . Aplicativos NET Core com facilidade.

No final de assistir este curso, você vai ser capaz de:

  • Como criar um modelo de dados usando fluxos de trabalho code-first e banco de dados

  • Comandos de estrutura de entidades

  • Como usar migrações para gerenciar alterações de banco de dados

  • Aplicar validações e restrições

  • Realize operações CRUD usando LINQ

  • Aplicar práticas recomendadas com Entity Framework

  • Como estender contextos de dados

  • Entenda como o rastreamento de alterações funciona.

  • Gerenciar estrutura de banco de dados usando API fluente

  • Lidar com relacionamentos individuais e presenciais

Pré-requisitos

Para fazer este curso, você deve ter pelo menos 3 meses de programação em C#. Se você precisar fortalecer seus fundamentos em C#, você pode usar meu Console de curso em C# e Desenvolvimento de Formulários do Windows com LINQ e ADO.NET

Conteúdo e visão geral

Para fazer este curso, você precisará ter algum conhecimento do C#. Mesmo que você não tenha muita exposição ao . Pilha de desenvolvimento NET, este curso é muito amigável para iniciantes e cheio de dicas de desenvolvimento.

Este curso premium é quebrado de forma inteligente para destacar um conjunto de atividades relacionadas com cada módulo no aplicativo que está sendo construído. Também vamos analisar erros de resolução de problemas e depuração enquanto avançamos; implementar melhores práticas; escrever lógica eficiente e entender por que desenvolvedores fazem as coisas da maneira que fazem. Seu conhecimento vai crescer, passo a passo, e você será desafiado a ser o melhor que pode ser.

Conheça seu professor

Teacher Profile Image

Trevoir Williams

Jamaican Software Engineer

Professor
Level: Intermediate

Nota do curso

As expectativas foram atingidas?
    Superou!
  • 0%
  • Sim
  • 0%
  • Um pouco
  • 0%
  • Não
  • 0%

Por que fazer parte da Skillshare?

Faça cursos premiados Skillshare Original

Cada curso possui aulas curtas e projetos práticos

Sua assinatura apoia os professores da Skillshare

Aprenda em qualquer lugar

Faça cursos em qualquer lugar com o aplicativo da Skillshare. Assista no avião, no metrô ou em qualquer lugar que funcione melhor para você, por streaming ou download.

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.