MISE À JOUR: J'ai reçu quelques votes positifs à ce sujet ces derniers temps, alors j'ai pensé que je ferais savoir aux gens que les conseils que je donnais ci-dessous n'étaient pas les meilleurs. Depuis que j'ai commencé à travailler avec Entity Framework sur d'anciennes bases de données sans clé, je me suis rendu compte que la meilleure chose que vous puissiez faire BY FAR est de le faire en inversant le code en premier. Il existe quelques bons articles sur la façon de procéder. Il vous suffit de les suivre, puis lorsque vous souhaitez y ajouter une clé, utilisez des annotations de données pour "truquer" la clé.
Par exemple, disons que je connais ma table Orders
, même si elle n'a pas de clé primaire, est assuré de n'avoir qu'un seul numéro de commande par client. Puisque ce sont les deux premières colonnes de la table, je configurerais les premières classes de code pour ressembler à ceci:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
En faisant cela, vous faîtes essentiellement croire à EF qu'il existe une clé en cluster composée de OrderNumber et de Customer. Cela vous permettra de faire des insertions, des mises à jour, etc. sur votre table sans clé.
Si vous n'êtes pas trop familier avec le code inversé en premier, allez trouver un bon didacticiel sur le code Entity Framework en premier. Ensuite, allez en trouver un sur Reverse Code First (qui fait Code First avec une base de données existante). Revenez ensuite ici et regardez à nouveau mes conseils clés. :)
Réponse originale :
Premièrement: comme d'autres l'ont dit, la meilleure option consiste à ajouter une clé primaire à la table. Arrêt complet. Si vous pouvez le faire, ne lisez pas plus loin.
Mais si vous ne pouvez pas, ou simplement vous détestez, il existe un moyen de le faire sans la clé primaire.
Dans mon cas, je travaillais avec un système hérité (à l'origine des fichiers plats sur un AS400 porté sur Access puis porté sur T-SQL). J'ai donc dû trouver un moyen. C'est ma solution. Ce qui suit a fonctionné pour moi en utilisant Entity Framework 6.0 (la dernière sur NuGet à ce jour).
Cliquez avec le bouton droit sur votre fichier .edmx dans l'Explorateur de solutions. Choisissez "Ouvrir avec ..." puis sélectionnez "Editeur XML (texte)". Nous allons modifier manuellement le code généré automatiquement ici.
Recherchez une ligne comme celle-ci:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">
Retirez store:Name="table_name"
de la fin.
Remplacer store:Schema="whatever"
parSchema="whatever"
Regardez en dessous de cette ligne et trouvez la <DefiningQuery>
balise. Il aura une grosse déclaration de sélection en elle. Retirez la balise et son contenu.
Maintenant, votre ligne devrait ressembler à ceci:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
Nous avons autre chose à changer. Parcourez votre dossier et trouvez ceci:
<EntityType Name="table_name">
À proximité, vous verrez probablement du texte commenté vous avertissant qu'aucune clé primaire n'a été identifiée, la clé a donc été déduite et la définition est une table / vue en lecture seule. Vous pouvez le laisser ou le supprimer. Je l'ai effacé.
Ci-dessous est la <Key>
balise. C'est ce qu'Entity Framework va utiliser pour insérer / mettre à jour / supprimer. ASSUREZ-VOUS DE FAIRE CE DROIT. La ou les propriétés de cette balise doivent indiquer une ligne identifiable de manière unique. Par exemple, disons que je connais ma table orders
, même si elle n'a pas de clé primaire, est assuré de n'avoir qu'un seul numéro de commande par client.
Donc le mien ressemble à:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
Sérieusement, ne faites pas cela mal. Disons que même s'il ne doit jamais y avoir de doublons, d'une manière ou d'une autre, deux lignes pénètrent dans mon système avec le même numéro de commande et le même nom de client. Whooops! C'est ce que j'obtiens pour ne pas utiliser de clé! J'utilise donc Entity Framework pour en supprimer un. Parce que je sais que le duplicata est la seule commande passée aujourd'hui, je fais ceci:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
Devine quoi? Je viens de supprimer le double ET l'original! C'est parce que j'ai dit à Entity Framework que order_number / cutomer_name était ma clé primaire. Donc, quand je lui ai dit de supprimer duplicateOrder, ce qu'il a fait en arrière-plan était quelque chose comme:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
Et avec cet avertissement ... vous devriez maintenant être prêt à partir!