web-dev-qa-db-fra.com

Impossible de mettre à jour EntitySet - car il contient un DefiningQuery et aucun élément <UpdateFunction> n'existe

J'utilise Entity Framework 1 avec .net 3.5.

Je fais quelque chose de simple comme ça:

var RoomDetails = context.Rooms.ToList();

foreach (var Room in Rooms)
{        
   Room.LastUpdated = DateTime.Now;
}

Je reçois cette erreur quand j'essaie de faire:

 context.SaveChanges();

Je reçois l'erreur:

Impossible de mettre à jour EntitySet - car il possède une DefiningQuery et aucun élément <UpdateFunction> n'existe dans l'élément <ModificationFunctionMapping> pour prendre en charge l'opération en cours.

Je fais beaucoup de mises à jour sur le contexte et je n’ai aucun problème, c’est seulement lorsque j’essaie de mettre à jour cette entité.

Toutes mes recherches montrent la même chose, à savoir qu'aucune clé primaire n'a été déclarée sur l'entité que je tente de mettre à jour. Mais hélas, j'ai une clé primaire déclarée ...

478
iKode

Cela se produit généralement pour l'une des raisons suivantes:

  • Le jeu d'entités est mappé à partir de la vue Base de données
  • Une requête de base de données personnalisée
  • La table de base de données n'a pas de clé primaire

Après cela, vous devrez peut-être toujours effectuer la mise à jour dans le concepteur Entity Framework (ou bien supprimer l'entité puis l'ajouter) avant de ne plus avoir l'erreur.

928
Ladislav Mrnka

Ajoutez simplement une clé primaire à la table. C'est tout. Problème résolu.

ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
82
Jebastin J

C'est le cas pour moi. La simple suppression entraîne une autre erreur. J'ai suivi les étapes de ce post sauf le dernier. Pour votre commodité, j'ai copié les 4 étapes du message que j'ai suivi pour résoudre le problème comme suit:

  1. Faites un clic droit sur le fichier edmx, sélectionnez Ouvrir avec, éditeur XML
  2. Localisez l'entité dans l'élément edmx: StorageModels
  3. Supprimer complètement le DefiningQuery
  4. Renommez le store:Schema="dbo" en Schema="dbo" (sinon, le code générera une erreur indiquant que le nom est invalide)
51
kavitha Reddy

Notez simplement que peut-être votre Entité a la clé primairemais votre table dans la base de données n'a pas la clé primaire

38
Majid

MISE À JOUR: J'ai eu quelques avis positifs à ce sujet récemment, alors j'ai décidé de faire savoir aux gens que les conseils que je donne ci-dessous ne sont pas les meilleurs. Depuis que j'ai commencé à utiliser Entity Framework avec de vieilles bases de données sans clé, je me suis rendu compte que la meilleure chose à faire PAR FAR est de le faire en inversant le code en premier. Il existe quelques bons articles sur la façon de procéder. Il suffit de les suivre et, lorsque vous souhaitez y ajouter une clé, utilisez des annotations de données pour "simuler" la clé. 

Par exemple, supposons que je connaisse ma table Orders, même si elle n'a pas de clé primaire, il est garanti de ne jamais avoir qu'un seul numéro de commande par client. Comme ce sont les deux premières colonnes de la table, je mettrais en place 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 faites 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 familiarisé avec la procédure inverse avec Code Code First, recherchez un bon tutoriel sur Entity Framework Code First. Ensuite, allez en chercher un sur Reverse Code First (qui utilise Code First avec une base de données existante). Ensuite, revenez ici et regardez à nouveau mes principaux conseils. :)

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 si vous 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, les fichiers plats d’un AS400 portés sur Access, puis sur T-SQL). Je devais donc trouver un moyen. Ceci est ma solution. Ce qui suit a fonctionné pour moi en utilisant Entity Framework 6.0 (le dernier sur NuGet à ce jour).

  1. 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 éditer à la main le code généré automatiquement ici.

  2. Cherchez une ligne comme celle-ci: 
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. Supprimez store:Name="table_name" de la fin.

  4. Remplacez store:Schema="whatever" par Schema="whatever"

  5. Regardez en dessous de cette ligne et trouvez la balise <DefiningQuery>. Il y aura une grosse déclaration choisie. Retirez la balise et son contenu.

  6. Maintenant, votre ligne devrait ressembler à ceci: 
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. Nous avons autre chose à changer. Parcourez votre fichier et trouvez ceci:
    <EntityType Name="table_name">

  8. À proximité, vous verrez probablement du texte commenté vous avertir qu'aucune clé primaire n'a été identifiée. La clé a donc été déduite et la définition est un tableau/vue en lecture seule. Vous pouvez le laisser ou le supprimer. Je l'ai supprimé.

  9. Ci-dessous, la balise <Key>. C'est ce que Entity Framework va utiliser pour insérer/mettre à jour/supprimer. SO 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, supposons que je connaisse ma table orders, même si elle n'a pas de clé primaire, il est garanti de ne jamais avoir qu'un seul numéro de commande par client. 

Alors le mien ressemble à:

<EntityType Name="table_name">
              <Key>
                <PropertyRef Name="order_numbers" />
                <PropertyRef Name="customer_name" />
              </Key>

Sérieusement, ne le faites pas mal. Disons que même s'il ne devrait jamais y avoir de doublons, deux lignes entrent dans mon système avec le même numéro de commande et le même nom de client. Whooops! C'est ce que je reçois 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 duplicata 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!

29
Pharylon

Cela peut également arriver si le modèle de données est obsolète.

J'espère que cela sauvera la frustration de quelqu'un d'autre :)

18
mob1lejunkie

Je recevais le même message d'erreur, mais dans mon scénario, j'essayais de mettre à jour des entités dérivées d'une relation plusieurs à plusieurs à l'aide d'un PJT (table de jonction pure).

En lisant les autres articles, je pensais pouvoir y remédier en ajoutant un champ PK supplémentaire à la table de jointure ... Cependant, si vous ajoutez une colonne PK à une table de jointure, ce n'est plus un PJT et vous perdez tous Les avantages du cadre d’entités, tels que le mappage automatique des relations entre les entités.

La solution dans mon cas a donc été de modifier la table de jointure de la base de données pour créer un PK qui inclut à la fois les deux colonnes d'ID étrangères.

6
Kerry Randolph

une erreur peut survenir si votre table n'a pas de clé primaire, dans ce cas, la table est en lecture seule et la commande db.SaveChanges () entraîne toujours une erreur

4
Ruben.sar

donc c'est vrai, il suffit d'ajouter une clé primaire

Remarque: assurez-vous que lorsque vous mettez à jour votre diagramme EF depuis la base de données que vous pointez vers la base de données right , dans mon cas, la chaîne de connexion pointait vers une base de données locale au lieu de la base de données correspondante. -date Dev DB, erreur d'écolier, je sais, mais je voulais poster ceci parce que cela peut être très frustrant si vous êtes convaincu que vous avez ajouté la clé primaire et que vous obtenez toujours la même erreur 

3
Spyder

J'ai eu le même problème. Comme ce fil a dit, Ma table n'avait pas de PK, alors j'ai défini le PK et ai exécuté le code. Mais malheureusement l'erreur est revenue. Ensuite, j'ai supprimé la connexion à la base de données (supprimez le fichier .edmx dans le dossier Model de l'Explorateur de solutions) et vous l'avez recréée. Erreur parti après cela. Merci à tous pour partager vos expériences. Cela fait gagner beaucoup de temps.

2
Namal

Définissez la clé primaire, puis enregistrez Table et Refresh, puis accédez à Model.edmx delete Table et obtenez-la à nouveau.

1
Joan Ali

J'avais ce problème parce que je générais mon EDMX à partir d'une base de données existante (conçue par quelqu'un d'autre et j'utilise le terme «conçu» de manière approximative ici).

Il s'avère que la table n'avait aucune clé. EF générait le modèle avec plusieurs clés multiples. Je devais ajouter une clé primaire à la table de la base de données en SQL, puis mettre à jour mon modèle dans VS. 

Cela a réglé le problème pour moi.

1
Stark

Il me suffisait de retirer la table du modèle et de le mettre à jour pour ramener la table. Je suppose que la clé primaire a été créée après que la table ait été insérée dans le modèle.

0
dangalg

J'ai eu exactement le même problème, malheureusement, l'ajout de la clé primaire ne résout pas le problème. Alors voici comment je résous le mien:

  1. Assurez-vous que vous avez un primary key sur la table afin que je modifie ma table et ajoute une clé primaire.
  2. Delete the ADO.NET Entity Data Model (fichier edmx) où je mappe et connecte avec ma base de données.
  3. Add again a new file of ADO.NET Entity Data Model pour me connecter à ma base de données et pour mapper les propriétés de mon modèle.
  4. Clean and rebuild the solution. 

Problème résolu.

0
Willy David Jr

L'ajout de la clé primaire a également fonctionné pour moi!

Une fois que cela est fait, voici comment mettre à jour le modèle de données sans le supprimer -

Cliquez avec le bouton droit de la souris sur la page du concepteur d'entités edmx et sur «Mettre à jour le modèle à partir d'une base de données».

0
Abhishek Poojary

Ouvrez votre fichier .edmx dans l'éditeur XML, puis supprimez la balise de Tag et changez également de magasin: Schema = "dbo" en Schema = "dbo" et reconstruisez la solution. L'erreur sera résolue et vous pourrez sauvegarder les données.

0
Sharad Tiwari

ajoutez simplement une clé primaire à votre table puis recréez votre EF

0
Sulyman

J'avais eu ce problème et je pensais que c'était dû au fait que j'avais supprimé l'index de la clé primaire de mes tables et que je l'avais remplacé par un index sur certains des autres champs du tableau.

Après avoir supprimé l'index de clé primaire et actualisé l'edmx, les insertions ont cessé de fonctionner. 

J'ai actualisé la table à l'ancienne version, actualisé edmx et tout fonctionne à nouveau. 

Je dois noter que lorsque j'ai ouvert EDMX pour résoudre ce problème, en vérifiant si une clé primaire avait été définie, il y en avait une. Donc, aucune des suggestions ci-dessus ne m'aidait. Mais rafraîchir l'index sur la clé primaire semblait fonctionner.

0
armstb01

Ce n'est pas une nouvelle réponse mais aidera quelqu'un qui ne sait pas comment définir une clé primaire pour sa table. Utilisez-le dans une nouvelle requête et exécutez-le. Cela définira la colonne UniqueID comme clé primaire.

USE [YourDatabaseName]
GO

Alter table  [dbo].[YourTableNname]
Add Constraint PK_YourTableName_UniqueID Primary Key Clustered (UniqueID);
GO
0
JessS