Entity Framework e design de banco de dados multi-tenancy

votos
7

Estou olhando para o design de esquema de banco de dados multi-tenancy para um conceito SaaS. Será ASP.NET MVC -> EF, mas isso não é tão importante.

Abaixo você pode ver um esquema exemplo de banco de dados (sendo o inquilino da Companhia). O CompanyId é replicado em todo o esquema e a chave primária foi colocado em ambos a chave natural, além de o inquilino Id.

Ligar o esquema para o Entity Framework dá os seguintes erros quando eu adicionar as tabelas no arquivo Modelo de Entidade (Model1.edmx):

  • A relação 'FK_Order_Customer' usa o conjunto de chaves estrangeiras '{Cliente, CompanyID}' que são parcialmente contidos no conjunto de chaves primárias '{orderId, CompanyID}' da 'Ordem' mesa. O conjunto de chaves estrangeiras devem ser totalmente contido no conjunto de chaves primárias, ou totalmente não contido no conjunto de chaves primárias para ser mapeado para um modelo.
  • A relação de 'FK_OrderLine_Customer' utiliza o conjunto de chaves estrangeiras '{customerId, CompanyID}' que são parcialmente contidas no conjunto de chaves primárias '{OrderLineId, CompanyID}' da tabela 'OrderLine'. O conjunto de chaves estrangeiras devem ser totalmente contido no conjunto de chaves primárias, ou totalmente não contido no conjunto de chaves primárias para ser mapeado para um modelo.
  • A relação de 'FK_OrderLine_Order' utiliza o conjunto de chaves estrangeiras '{orderId, CompanyID}' que são parcialmente contidas no conjunto de chaves primárias '{OrderLineId, CompanyID}' da tabela 'OrderLine'. O conjunto de chaves estrangeiras devem ser totalmente contido no conjunto de chaves primárias, ou totalmente não contido no conjunto de chaves primárias para ser mapeado para um modelo.
  • A relação 'FK_Order_Customer' usa o conjunto de chaves estrangeiras '{Cliente, CompanyID}' que são parcialmente contidos no conjunto de chaves primárias '{orderId, CompanyID}' da 'Ordem' mesa. O conjunto de chaves estrangeiras devem ser totalmente contido no conjunto de chaves primárias, ou totalmente não contido no conjunto de chaves primárias para ser mapeado para um modelo.
  • A relação de 'FK_OrderLine_Customer' utiliza o conjunto de chaves estrangeiras '{customerId, CompanyID}' que são parcialmente contidas no conjunto de chaves primárias '{OrderLineId, CompanyID}' da tabela 'OrderLine'. O conjunto de chaves estrangeiras devem ser totalmente contido no conjunto de chaves primárias, ou totalmente não contido no conjunto de chaves primárias para ser mapeado para um modelo.
  • A relação de 'FK_OrderLine_Order' utiliza o conjunto de chaves estrangeiras '{orderId, CompanyID}' que são parcialmente contidas no conjunto de chaves primárias '{OrderLineId, CompanyID}' da tabela 'OrderLine'. O conjunto de chaves estrangeiras devem ser totalmente contido no conjunto de chaves primárias, ou totalmente não contido no conjunto de chaves primárias para ser mapeado para um modelo.
  • A relação de 'FK_OrderLine_Product' utiliza o conjunto de chaves estrangeiras '{ProductId, CompanyID}' que são parcialmente contidas no conjunto de chaves primárias '{OrderLineId, CompanyID}' da tabela 'OrderLine'. O conjunto de chaves estrangeiras devem ser totalmente contido no conjunto de chaves primárias, ou totalmente não contido no conjunto de chaves primárias para ser mapeado para um modelo.

A questão é em duas partes:

  1. É meu projeto de banco de dados incorreta? Devo abster-se de essas chaves primárias compostas? Estou questionando minha sanidade relativa a design esquema fundamental (síndrome cerebral frazzled). Por favor, fique à vontade para sugerir o esquema 'idealizada'.
  2. Alternativamente, se o projeto de banco de dados estiver correta, então é EF incapaz de combinar as chaves porque percebe essas chaves estrangeiras como um potencial mis-configurado 1: 1 relações (incorretamente)? Nesse caso, este é um bug EF e como posso resolver isso?

Multi-tenancy esquema do banco http://i46.tinypic.com/23si52u.png

Publicado 30/05/2010 em 13:33
fonte usuário
Em outras línguas...                            


5 respostas

votos
4

Em uma varredura rápida de mensagens de erro da EF, é evidente que não gosto do jeito que você estiver configurando chaves compostas, e eu acho que provavelmente está empurrando-lo na direção certa. Dê algum pensamento novamente para o que faz com que suas chaves primárias único. É o OrderID por si só não exclusivo, sem um CompanyID? um ProductID não é único, sem um CompanyID? Um OrderLine certamente deve ser único sem um CompanyID, uma vez que um OrderLine deve ser associado apenas com uma única ordem.

Se você realmente precisa do CompanyID para todos eles, o que provavelmente significa que a empresa em questão está fornecendo-lhe com ProductID e OrderID, então você pode querer ir numa direção diferente, e gerar suas próprias chaves primárias que não são intrínsecas aos dados . Basta configurar uma coluna de auto incremento para a sua chave primária, e deixe estes ser o OrderID interna, OrderLineID, ProductID, CompanyID, etc. Nesse ponto, o OrderLine não vai precisar do cliente OrderID ou CompanyID; a referência de chave estrangeira para a Ordem seria seu ponto de partida. (E o Cliente nunca deve ser um atributo de uma linha de pedido, é um atributo da ordem, não a linha de ordem.)

chaves compostas são apenas confuso. Tentar projetar o modelo sem eles, e ver se ele simplifica as coisas.

Respondeu 30/05/2010 em 13:43
fonte usuário

votos
2

Eu acho que o erro não está no design. Não está na EF. É nas relações SQL Server.

Leia a mensagem de EF:

A relação 'FK_Order_Customer' usa o conjunto de chaves estrangeiras '{Cliente, CompanyID}' que são parcialmente contidos no conjunto de chaves primárias '{orderId, CompanyID}' da 'Ordem' mesa. O conjunto de chaves estrangeiras devem ser totalmente contido no conjunto de chaves primárias, ou totalmente não contido no conjunto de chaves primárias para ser mapeado para um modelo.

ERRO

Actualy a relação betwen Ordem e cliente uso apenas um campo (provavelmente você arrastado com o mouse no campo "CustomerId" do da tabela Order para o "Id" da tabela de Cliente)

SOLUÇÃO

Botão direito do mouse sobre o fio que se conectam Ordem e do cliente e na relação adicionar também o CompanyId


PS: O projeto está correto.

Colocar o CompanyId em cada tabela é a solução rith em arquitetura multi-tenant porque ajuda a escala (normalmente sempre quero selecionar apenas registros da empresa LoggedIn).

Respondeu 12/11/2010 em 10:16
fonte usuário

votos
2

Eu acho que armazenar o número da companhia em cada uma das mesas está prejudicando mais do que ajudando. Eu posso entender por que você quer fazer isso (como o programador / dba você pode simplesmente entrar em qualquer mesa e 'ver' os dados que pertence a quem que é reconfortante), mas ele está ficando no caminho de você configurar o banco de dados do assim que deve ser.

Evite as chaves compostas e seu projeto fica muito mais simples.

Respondeu 30/05/2010 em 14:19
fonte usuário

votos
0

Primeiro: como os outros disse, ao fazer referência a uma chave estrangeira, use toda a chave primária em outra tabela (ou seja, ambos os campos.).

Segundo, eu não posso imaginar não usando uma coluna CompanyID na maioria das mesas em uma aplicação séria. OrderDetail pode talvez ser uma exceção neste caso (também tabelas de pesquisa globais talvez, a menos que sejam inquilino dependente). A coisa é, você não pode fazer qualquer tipo de seguro formulário de pesquisa livre em uma mesa sem qualquer adição da CompanyID, ou fazer JOINs até o ponto de chegar a uma tabela que tem essa coluna. Este último, obviamente, custa desempenho. Talvez neste caso, você poderia fazer uma exceção para OrderDetail e só pesquisar na versão juntou (apenas duas mesas). Então, novamente, não é realmente consistente.

Ainda sobre fazer uma uma chave composta ou não: a sua possível, mas abre a possibilidade de que um bug grava informações de forma incorrecta (em inexistente, ou outras administrações das pessoas) para a duração do bug. Tentar corrigir isso na produção, para não mencionar explicar aos clientes porque não estão vendo suas ordens concorrentes em seu sistema.

Respondeu 26/10/2013 em 01:28
fonte usuário

votos
0

Se você tem que adicionar absolutamente coluna CompanyID para cada tabela, adicioná-lo como uma coluna regular e não uma chave composta. chave composta é usado principalmente quando você tem que implementar muitos para muitos relação.

Como alguém mencionou também criar um índice não agrupado em CompanyID assim junta-se à mesa da Companhia são beneficiados.

Obrigado!

Respondeu 26/08/2013 em 13:12
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more