Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Atualizar o valor da chave primária usando a estrutura de entidade


Eu tenho um Ph.D. in cs - na área de Bancos de Dados, então esta resposta será um pouco diferente da perspectiva dos programadores. Com todo o respeito a Oliver Hanappi, uma chave pode e ocasionalmente muda se não for uma chave substituta. Por exemplo. Uma chave natural ou uma chave composta. Por exemplo. É possível alterar seu SSN nos EUA. Mas muitos programadores ao longo dos anos considerariam isso uma chave imutável e a usariam como tal. É muito mais comum alterar uma chave primária composta composta por chaves estrangeiras.

Estou lidando com um banco de dados que tem um relacionamento ternário. Especificamente três entidades (com chaves estrangeiras sendo chaves primárias substitutas em suas respectivas tabelas). No entanto, para preservar o relacionamento entre duas entidades ao alterar a terceira entidade requer alterar parte da chave primária da tabela de interseção (também chamada de tabela de junção pura no MSDN). Este é um design válido e só pode ser melhorado removendo a tabela de interseção de relacionamento ternário e substituindo-a por duas tabelas de relacionamento binário (que podem ter suas próprias chaves substitutas). A EF lidaria com isso. Essa mudança de design faria um modelo (Muitos->muitos)->muitos ou Pai1-Parent2 -> Filho-neto (se isso não estiver claro, leia o exemplo abaixo). A estrutura de entidade funcionaria bem com isso, pois cada relacionamento é realmente um relacionamento de um para muitos. Mas é um design maluco do ponto de vista do DB. Deixe-me mostrar-lhe um exemplo do porquê.

Considere que Curso, Sala de Aula e Instrutor estão associados um ao outro em uma aula. A classe pode incluir:CourseID, ClassroomID, InstructorID como chaves estrangeiras e conter uma chave primária composta, incluindo todas as três. Embora seja um modelo ternário claro e conciso (relação de 3 vias), poderíamos dividi-lo em relações binárias. Isso daria duas tabelas de interseção. A adição de chaves substitutas satisfaria a EF da seguinte forma:

Class(SurrogateKeyClass , ID do Instrutor , CursoID )

ClassRoomUsed(SurrogateKeyClassroomUsed , SurrogateKeyClass , ClassRoomID )

O problema com esse design é que poderíamos ter o mesmo curso e instrutor associados várias vezes, o que o modelo anterior evita. Para evitar esse problema, você pode adicionar uma restrição no banco de dados para exclusividade dos dois campos de ID, mas por que você deseja fazer isso quando está lidando apenas com chaves substitutas para começar? No entanto, esta solução funcionaria da melhor maneira possível. No entanto, este não é um design de banco de dados lógico devido à restrição não natural necessária no banco de dados.

MAS, se você não quiser alterar seu banco de dados ou não puder alterar seu banco de dados, aqui está uma segunda solução :As tabelas de interseção/associação são apenas isso, links ligando duas ou mais entidades. Se uma for alterada, exclua a associação e recrie uma nova que tenha as chaves estrangeiras apropriadas (propriedades de navegação). Isso significa que você não poderá exigir entidades filhas em nenhum dos relacionamentos, mas isso é extremamente comum.

Eu sugeriria que o Entity Framework (no futuro) permita que aqueles de nós que possam projetar um modelo de banco de dados elegante alterem partes de chaves em tabelas de interseção/associação quando quisermos!

Outro exemplo de graça:

Considere uma Associação de Estudantes, Cursos e Séries. Os alunos são associados a um curso por meio de uma nota. Normalmente, esta é uma associação de muitos para muitos entre o Aluno e um Curso com um campo adicional na tabela de associação chamado nota (as tabelas de associação têm dados de carga como nota, as tabelas de interseção não têm carga e são referenciadas no MSDN como tabelas de junção puras em locação em um só lugar):

Aluno(ID Aluno , ....)

Curso(CursoID , ...)

Tomando(ID do Aluno , ID do curso , grau)

Se alguém cometer um erro de entrada de dados em uma lista suspensa e colocar um aluno na turma errada, você quer que ele altere depois selecionando a lista suspensa novamente e selecionando um curso diferente. Em segundo plano, você precisará excluir o objeto EF da tabela Taking e recriá-lo sem perder uma nota, se houver. Basta alterar a chave estrangeira CourseID parece uma alternativa melhor. Crie sua própria associação se esta parecer artificial, mas como professor foi natural para mim.

Conclusão:Quando você tem uma sequência de relacionamentos, pode ser melhor não permitir o cascateamento e/ou alterar o FK, mas existem cenários lógicos/ressonáveis ​​onde isso é necessário, mesmo que não seja recomendado como uma prática recomendada em geral .

Esse problema pode se manifestar com as seguintes exceções, dependendo se você estiver alterando a propriedade de navegação ou a propriedade de chave no modelo, respectivamente:

Ocorreu uma violação de restrição de integridade referencial:uma propriedade de chave primária que faz parte da restrição de integridade referencial não pode ser alterada quando o objeto dependente é Inalterado, a menos que esteja sendo definido para o objeto principal da associação. O objeto principal deve ser rastreado e não marcado para exclusão.

A propriedade 'X' faz parte da informação chave do objeto e não pode ser modificada.