Iniciando alguns projetos com o EF, mas eu tinha algumas perguntas sobre junção de tabelas e chaves, etc. Digamos que eu tenho uma tabela de aplicativos e uma tabela de permissões. Os aplicativos têm muitas permissões e cada permissão pode pertencer a muitos aplicativos (muitos para muitos).
Agora, as tabelas de Aplicação e Permissão são fáceis:
Applications
--------------
PK ApplicationID
Name
Permissions
--------------
PK PermissionID
Name
Mas qual é a MELHOR maneira de fazer a tabela de junção? Eu tenho essas duas opções:
ApplicationPermissions
-----------------------
PK ApplicationPermissionID
CU ApplicationID
CU PermissionID
OU
ApplicationPermissions
-----------------------
CPK ApplicationID
CPK PermissionID
PK = Primary Key
CPK = Composite Primary Key
CU = Composite Unique Index
Você já foi queimado fazendo isso de uma maneira sobre a outra? é estritamente preferência? Ocorreu-me que muitas "diferenças" serão abstraídas pelo meu padrão de repositório (por exemplo, eu quase nunca criaria um objeto de permissão inteiro e o adicionaria a um aplicativo, mas por ID ou nome exclusivo ou alguma coisa), mas acho que estou procurando histórias de horror, de um jeito ou de outro.
fonte
Ao longo dos anos, adquiri o hábito de atribuir a cada tabela "TableName" uma chave primária gerada automaticamente "TableNameID", sem exceções, nem mesmo para tabelas de junção. Posso dizer que nunca me arrependi disso, porque isso facilita muitas coisas ao criar código genérico que faz algo para "todas as tabelas" ou "algumas tabelas" ou "muitas linhas de várias tabelas diferentes".
Por exemplo, se alguém solicitar que você armazene algumas linhas de tabelas diferentes (ou referências a essas) em um arquivo ou na memória, por exemplo, para fins de registro, será muito útil quando você souber de antemão que só precisa armazenar exatamente uma nome da tabela e exatamente um ID inteiro, e você não precisa lidar com nenhum "caso especial".
Outra coisa, quando você inicia com PKs combinadas, provavelmente, algumas vezes mais tarde, encontra a necessidade de chaves estrangeiras combinadas (já que você pode chegar a um ponto em que deseja adicionar uma referência FK à sua
ApplicationPermissions
tabela). O próximo requisito pode ser que esse FK seja exclusivo em conjunto com outros atributos ou chaves estrangeiras - o que resultará em maior complexidade geral. Obviamente, nada que não seja possível manipular para os sistemas de banco de dados mais modernos, mas uma solução uniforme facilita muito a vida dos programadores.E, finalmente, uma declaração como
SELECT ... FROM TABLE WHERE TableNameID IN (id1,id2,...)
funciona bem com uma única coluna como chave primária, mas nunca vi um dialeto SQL até agora que permita fazer isso com chaves combinadas. Se você sabe de antemão que nunca precisará de uma consulta como essa, tudo bem, mas não se surpreenda se amanhã você receber um requisito que será resolvido mais facilmente com esse tipo de SQL.Obviamente, quando você espera que sua
ApplicationPermissions
tabela mantenha várias centenas de milhões de linhas, considere evitar algo como aApplicationPermissionsID
.fonte
Embora a resposta de Mike seja boa, aqui estão as razões pelas quais eu adicionaria ou não um campo de identificação separado.
Considere usar um campo de ID separado para a tabela de junção / junção se ela contiver campos diferentes do ID . Isso tende a notar que é uma entidade de primeira classe.
Considere usar um campo de ID separado se as APIs ou qualquer lógica existente tenderem a usar campos únicos para recuperar / editar entidades. Isso pode ajudar outras pessoas a seguir seu código no contexto de um projeto maior.
Não use se não houver benefício específico (KISS). A EF sabe como lidar com esse tipo de tabela e uma restrição exclusiva composta às vezes pode ser perdida quando outras pessoas estão tentando entender esse tipo de relacionamento. Além disso, ao normalizar, tento usar a menor chave possível que define exclusivamente a tupla . No seu segundo exemplo, você possui 2 chaves primárias candidatas separadas.
fonte
Lembre-se de criar um índice e uma chave estrangeira em ambos
PersonId
eAddressId
.Não importa o que os outros pensem ser "melhor" ou "você deveria", esta é a maneira mais simples e fácil de permitir que o banco de dados funcione corretamente.
fonte
PersonAddress
linhas com valoresPersonId
e idênticosAddressId
.