183 votes

Entity Framework : table sans clé primaire

Je dispose d'une base de données existante avec laquelle je souhaite créer une nouvelle application en utilisant les éléments suivants EF4.0

Certaines tables n'ont pas de clés primaires définies, de sorte que lorsque je crée un nouveau modèle de données d'entité, j'obtiens le message suivant :

The table/view TABLE_NAME does not have a primary key defined 
and no valid primary key could be inferred. This table/view has 
been excluded. To use the entity, you will need to review your schema, 
add the correct keys, and uncomment it.

Si je veux les utiliser et modifier les données, dois-je nécessairement ajouter un PK à ces tables, ou existe-t-il une solution de contournement pour ne pas avoir à le faire ?

22 votes

Pour citer Joe Celko : si elle n'a pas de clé primaire, ce n'est pas une table . Pourquoi diable quelqu'un créerait-il une table "normale" sans clé primaire ? Ajoutez simplement ces PK ! Vous en aurez besoin - plutôt tôt que tard....

2 votes

+1 même si vous avez cité celko ;-)

4 votes

Si c'est une vue ce hava un regard ce cas stackoverflow.com/a/10302066/413032

107voto

Colin Points 733

Je pense que ce problème est résolu par Tillito :

Entity Framework et SQL Server View

Je cite son texte ci-dessous :

Nous avons eu le même problème et voici la solution :

Pour forcer le cadre de l'entité à utiliser une colonne comme clé primaire, utilisez ISNULL.

Pour forcer le cadre de l'entité à ne pas utiliser une colonne comme clé primaire, utilisez NULLIF.

Une façon simple de l'appliquer est d'envelopper l'instruction select de votre vue dans une autre select.

Exemple :

SELECT
  ISNULL(MyPrimaryID,-999) MyPrimaryID,
  NULLIF(AnotherProperty,'') AnotherProperty
  FROM ( ... ) AS temp

répondu le 26/04/10 à 17:00 par Tillito

6 votes

+1 C'est la bonne réponse. Dans un monde parfait, il serait formidable de modifier toutes les bases de données existantes pour qu'elles aient une intégrité référentielle, mais en réalité, ce n'est pas toujours possible.

9 votes

Je ne le recommanderais pas. En particulier la partie ISNULL. Si EF détecte deux PK identiques, il se peut qu'il ne rende pas le ou les enregistrements uniques et renvoie un objet partagé. Cela m'est déjà arrivé.

0 votes

@Todd -- comment cela pourrait-il arriver si MyPrimaryID est une colonne NOT NULL ?

65voto

Dave Markle Points 44637

L'erreur signifie exactement ce qu'elle dit.

Même si vous pouviez contourner ce problème, croyez-moi, vous ne le voudriez pas. Le nombre de bogues déroutants qui pourraient être introduits est stupéfiant et effrayant, sans parler du fait que vos performances risquent de s'effondrer.

Ne travaillez pas autour de ça. Corrigez votre modèle de données.

EDITAR: J'ai vu qu'un certain nombre de personnes ont voté contre cette question. C'est très bien, je suppose, mais gardez à l'esprit que l'OP a demandé à ce que l'on mette en correspondance un tableau sans clé primaire, pas un voir . La réponse est toujours la même. Contourner le besoin de l'EF d'avoir un PK sur les tables est une mauvaise idée du point de vue de la facilité de gestion, de l'intégrité des données et des performances.

Certains ont fait remarquer qu'ils n'ont pas la possibilité de corriger le modèle de données sous-jacent parce qu'ils établissent une correspondance avec une application tierce. Ce n'est pas une bonne idée, car le modèle peut changer sous vos yeux. Dans ce cas, il est possible que vous souhaitiez établir une correspondance avec une vue, ce qui, une fois encore, n'est pas la question posée par le PO.

56 votes

Je suis d'accord dans les scénarios courants, mais dans les scénarios rares comme la table LOG, vous avez juste besoin d'insérer des enregistrements dès que possible. Avoir un PK peut être un problème lors de la vérification de l'unicité et de l'indexation. De plus, si votre PK est IDENTITE, le retour de la valeur générée à l'EF est un autre problème. En utilisant GUID à la place ? le temps de génération et l'indexation/tri est un autre problème !...Donc dans certains scénarios OLTP critiques (comme Logging) ne pas avoir de PK est un point et l'avoir n'a aucun point positif !

5 votes

@MahmoudMoravej : Tout d'abord, ne mélangez pas les idées d'index de clustering et de clés primaires. Ce n'est pas la même chose. Vous pouvez avoir des insertions très performantes sur des tables avec des index en cluster sur des colonnes IDENTITY. Si vous rencontrez des problèmes avec la maintenance des index, vous devez partitionner la table correctement. Laisser une table sans index clusterisé signifie également que vous ne pouvez pas la défragmenter efficacement pour récupérer de l'espace après les suppressions. Je plains la pauvre personne qui essaiera d'interroger votre table de journalisation si elle n'a pas d'index.

1 votes

Merci Dave, tu m'as fait réfléchir :-) Je ne savais pas que l'on pouvait avoir des PK non clusterisées (bien que leurs performances soient inférieures à celles des PK clusterisées dans la vérification de l'unicité, n'est-ce pas ? spécialement dans les PK d'IDENTITÉ lorsque la nouvelle insertion sera placée à la fin de la table).

6voto

Dusty Roberts Points 1533

N'essayez pas de le contourner... créez simplement la clé primaire, EF Needs.

4voto

Erick T Points 1579

EF ne nécessite pas de clé primaire sur la base de données. Si c'était le cas, vous ne pourriez pas lier les entités aux vues.

Vous pouvez modifier la SSDL (et la CSDL) pour spécifier un champ unique comme clé primaire. Si vous n'avez pas de champ unique, alors je crois que vous êtes fichu. Mais vous devriez vraiment avoir un champ unique (et une clé primaire), sinon vous allez rencontrer des problèmes plus tard.

Erick

0 votes

Cela permet d'éviter le piratage de ISNULL. Mais selon la situation, d'autres réponses peuvent être nécessaires - j'ai l'impression que certains types de données ne sont pas supportés pour un PK dans EF par exemple.

3voto

Jaba jubhyl Points 64

CETTE SOLUTION FONCTIONNE

Vous n'avez pas besoin de cartographier manuellement, même si vous n'avez pas de PK. Il suffit de dire à l'EF que l'une de vos colonnes est un index et que la colonne index n'est pas nullable.

Pour ce faire, vous pouvez ajouter un numéro de rangée à votre vue avec la fonction isNull comme suit

select 
    ISNULL(ROW_NUMBER() OVER (ORDER BY xxx), - 9999) AS id
from a

ISNULL(id, number) est le point clé ici car il indique à l'EF que cette colonne peut être une clé primaire.

2 votes

Je ne suggérerais pas la partie ISNULL cependant. Si EF détecte deux PK identiques, il peut ne pas rendre l'enregistrement unique et renvoyer un objet partagé. Cela m'est déjà arrivé.

1 votes

Vous devez utiliser isnull, sinon EF ne croira pas qu'il n'est pas nullable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X