Impossibile aggiornare EntitySet - perché ha un DefiningQuery e non esiste alcun elemento <UpdateFunction>


534

Sto usando Entity Framework 1 con .net 3.5.

Sto facendo qualcosa di semplice come questo:

var roomDetails = context.Rooms.ToList();

foreach (var room in roomDetails)
{        
   room.LastUpdated = DateTime.Now;
}

Ricevo questo errore quando provo a fare:

 context.SaveChanges();

Ottengo l'errore:

Impossibile aggiornare EntitySet - perché ha un DefiningQuery e non esiste alcun elemento <UpdateFunction> nell'elemento <ModificationFunctionMapping> per supportare l'operazione corrente.

Sto facendo molti aggiornamenti sul contesto e senza problemi, è solo quando provo ad aggiornare questa particolare entità.

Tutta la mia ricerca mostra la stessa cosa, che non esiste una chiave primaria dichiarata sull'entità che sto cercando di aggiornare. Ma ahimè, ho una chiave primaria dichiarata ...


61
Ho fatto un errore, non c'era una chiave primaria impostata sul tavolo, grazie per il tuo tempo! Ci dispiace per l'inconvenienza!
iKode,

1
Mi è appena successo - probabilmente ho creato 1000 tabelle con chiavi primarie e me ne sono dimenticato - il messaggio di eccezione non aiuta molto
Peter Munnings

1
eccellente. ho davvero dimenticato di aggiungere la chiave primaria alla tabella. Proviamo a stare attenti)
AEMLoviji

Risposte:


1024

Di solito succede perché uno dei seguenti motivi:

  • Il set di entità è mappato dalla vista Database
  • Una query di database personalizzata
  • La tabella del database non ha una chiave primaria

Dopo averlo fatto, potrebbe essere necessario aggiornare nella finestra di progettazione Entity Framework (o in alternativa eliminare l'entità e quindi aggiungerla) prima di interrompere l'errore.


2
Assicurati di cambiare anche store: Schema in solo Schema per quel EntitySet, se hai ancora problemi.
Geoff,

53
Quindi eliminare e ricreare l'entità perché l'aggiornamento non funziona correttamente nel designer EF.
Suncat2000,

48
PK era la risposta. Grazie!
inserito il

1
L'aggiornamento nel designer EF ha funzionato bene per me dopo aver aggiunto la chiave primaria al database. Utilizzo di EF 5.0 e .net 4.0
StillLearnin

1
Anch'io ! Grazie ... ho dovuto rimuovere la tabella e aggiungere di nuovo a EF per farlo prendere
ajzeffer

90

Aggiungi solo una chiave primaria alla tabella. Questo è tutto. Problema risolto.

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

13
e non dimenticare di fare clic su "Aggiorna modello dal database" sul tuo file .edmx
Bashar Abu Shamaa,

@BasharAbuShamaa questa risposta non è valida senza quel dettaglio.
Kehlan Krumme,

66

Questo è il caso per me. La semplice rimozione ha provocato un altro errore. Ho seguito i passaggi di questo post tranne l'ultimo. Per comodità, ho copiato i 4 passaggi dal post che ho seguito per risolvere il problema come segue:

  1. Fare clic con il tasto destro sul file edmx, selezionare Apri con, editor XML
  2. Individua l'entità nell'elemento edmx: StorageModels
  3. Rimuovere interamente DefiningQuery
  4. Rinomina store:Schema="dbo"in Schema="dbo"(altrimenti, il codice genererà un errore che dice che il nome non è valido)

Grazie mille - questo è esattamente ciò che ha risolto il mio problema. Abbastanza inquietante che questo non sia stato risolto in EF. E, abbastanza sorprendente che tu l'abbia capito!
Bicycle Dave,

Ho provato a eliminare l'entità e ad aggiungerla nuovamente. Ricompilazione. Pulizia. Niente ha funzionato per me tranne questo.
vintastic

1
Ciò ha risolto il mio problema, ma non so come hai trovato le risposte e perché il tuo suggerimento ha risolto il problema.
Swcraft,

Cosa succede se è necessario aggiornare il modello di database? Ho fatto un "Modello di aggiornamento dal database" e il mio modello è rimasto totalmente inutilizzabile. Ho dovuto annullare e ricominciare da capo. Se c'è un modo per aggirare questo?
Gary,

Questo è un problema davvero strano. Ci sono informazioni su come si verifica questo problema per evitarlo? Tuttavia - ha aiutato
r3dst0rm

41

Basta notare che forse la tua Entità ha la chiave primaria ma la tua tabella nel database non ha la chiave primaria .


1
Come superare, se non possiamo modificare la tabella del database?
Kai Hartmann,

Se puoi modificare la tabella DB per avere una chiave primaria, il generatore di codice smetterà di fare gli stessi errori, la rimozione della chiave da EF causerà molti altri problemi.
Chris Schaller,

30

AGGIORNAMENTO: Ultimamente ho ricevuto alcuni voti a riguardo, quindi ho pensato di far sapere alla gente che i consigli che fornisco di seguito non sono i migliori. Da quando inizialmente ho iniziato a fare confusione con Entity Framework su vecchi database senza chiave, sono arrivato a capire che la cosa migliore che puoi fare DA FAR è farlo prima in codice inverso. Ci sono alcuni buoni articoli là fuori su come farlo. Seguili e, quando vuoi aggiungere una chiave, usa le annotazioni dei dati per "falsificare" la chiave.

Ad esempio, supponiamo che conosca la mia tabella Orders, sebbene non abbia una chiave primaria, è assicurato che abbia sempre un solo numero d'ordine per cliente. Dato che quelle sono le prime due colonne sul tavolo, imposterò il codice delle prime classi in questo modo:

    [Key, Column(Order = 0)]
    public Int32? OrderNumber { get; set; }

    [Key, Column(Order = 1)]
    public String Customer { get; set; }

In questo modo, fondamentalmente sei falso EF nel credere che ci sia una chiave cluster composta da OrderNumber e Customer. Questo ti permetterà di fare inserimenti, aggiornamenti, ecc. Sulla tua tabella senza chiave.

Se non si ha troppa familiarità con il primo codice inverso, andare prima a trovare un buon tutorial su Entity Framework Code. Quindi vai a trovarne uno su Reverse Code First (che sta eseguendo Code First con un database esistente). Quindi torna qui e guarda di nuovo i miei consigli chiave. :)

Risposta originale :

Primo: come altri hanno già detto, l'opzione migliore è aggiungere una chiave primaria alla tabella. Punto. Se puoi farlo, non leggere oltre.

Ma se non puoi, o semplicemente odi te stesso, c'è un modo per farlo senza la chiave primaria.

Nel mio caso, stavo lavorando con un sistema legacy (originariamente file flat su un AS400 portati su Access e poi portati su T-SQL). Quindi ho dovuto trovare un modo. Questa è la mia soluzione Quanto segue ha funzionato per me usando Entity Framework 6.0 (l'ultimo su NuGet al momento della stesura).

  1. Fare clic con il tasto destro del mouse sul file .edmx in Esplora soluzioni. Scegli "Apri con ...", quindi seleziona "Editor XML (testo)". Modificheremo manualmente il codice generato automaticamente qui.

  2. Cerca una linea come questa:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. Rimuovi store:Name="table_name"dalla fine.

  4. Cambia store:Schema="whatever"inSchema="whatever"

  5. Guarda sotto quella linea e trova il <DefiningQuery>tag. Avrà una grande dichiarazione selezionata in esso. Rimuovi il tag e il suo contenuto.

  6. Ora la tua linea dovrebbe assomigliare a questa:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. Abbiamo qualcos'altro da cambiare. Passa attraverso il tuo file e trova questo:
    <EntityType Name="table_name">

  8. Nelle vicinanze probabilmente vedrai del testo commentato che ti avverte che non è stata identificata una chiave primaria, quindi la chiave è stata dedotta e la definizione è una tabella / vista di sola lettura. Puoi lasciarlo o cancellarlo. L'ho cancellato.

  9. Di seguito è riportato il <Key>tag. Questo è ciò che Entity Framework utilizzerà per eseguire l'inserimento / aggiornamento / eliminazione. Quindi assicurati di fare questo diritto. La proprietà (o proprietà) in quel tag deve indicare una riga identificabile in modo univoco. Ad esempio, supponiamo che conosca la mia tabella orders, sebbene non abbia una chiave primaria, è assicurato che abbia sempre un solo numero d'ordine per cliente.

Quindi il mio assomiglia a:

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

Seriamente, non fare questo male. Diciamo che anche se non dovrebbero mai esserci duplicati, in qualche modo due file entrano nel mio sistema con lo stesso numero d'ordine e nome cliente. Whooops! Questo è quello che ottengo per non usare una chiave! Quindi uso Entity Framework per eliminarne uno. Poiché so che il duplicato è l'unico ordine effettuato oggi, faccio questo:

var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);

Indovina un po? Ho appena eliminato sia il duplicato che l'originale! Questo perché ho detto a Entity Framework che order_number / cutomer_name era la mia chiave primaria. Quindi quando gli ho detto di rimuovere duplicateOrder, quello che ha fatto in background è stato qualcosa del tipo:

DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)

E con quell'avvertimento ... ora dovresti essere bravo ad andare!


Ho trovato questa risposta dopo aver trovato la stessa soluzione al problema. Sicuramente la risposta corretta! Solo la definizione di una chiave primaria come quella menzionata in altre risposte non aiuta in molti casi.
Obl Tobl,

19

Questo può accadere anche se il modello di dati non è aggiornato.

Spero che questo salverà la frustrazione di qualcun altro :)


6

Stavo ricevendo lo stesso messaggio di errore, ma nel mio scenario stavo cercando di aggiornare entità derivate da una relazione molti-a-molti usando una PJT (Pure Join Table).

Dalla lettura degli altri post, ho pensato di poterlo risolvere aggiungendo un campo PK aggiuntivo alla tabella di join ... Tuttavia, se aggiungi una colonna PK a una tabella di join, non è più un PJT e perdi tutto il vantaggi del framework delle entità come la mappatura automatica delle relazioni tra le entità.

Quindi la soluzione nel mio caso era quella di modificare la tabella di join sul DB per creare un PK che includesse ENTRAMBE le colonne ID esterne.


È così che ha sempre funzionato la generazione di EDMX? Sono abituato a lavorare con Code First che non richiede un PK su una tabella di join pura.
Michael Hornfeck,

4

potrebbe verificarsi un errore, se la tabella non ha una chiave primaria, in questo caso la tabella è "sola lettura" e il comando db.SaveChanges () porterà sempre un errore


4

Imposta la chiave primaria, quindi salva la tabella e aggiorna, quindi vai su Model.edmx elimina la tabella e riavvia.


3

quindi è vero, basta aggiungere una chiave primaria

Nota: assicurarsi che quando si aggiorna il diagramma EF dal database che si sta puntando al database giusto , nel mio caso la stringa di connessione puntava a un DB locale anziché al DB di sviluppo aggiornato, scolaro errore lo so, ma volevo postarlo perché può essere molto frustrante se sei convinto di aver aggiunto la chiave primaria e stai ancora ottenendo lo stesso errore


2

Ho avuto lo stesso problema. Come diceva questo thread, la mia tabella non aveva un PK, quindi ho impostato il PK ed eseguito il codice. Ma purtroppo l'errore è venuto di nuovo. Quello che ho fatto dopo è stato, eliminare la connessione DB (eliminare il file .edmx nella cartella Model di Solution Explorer) e ricrearla. Errore andato dopo. Grazie a tutti per aver condiviso le vostre esperienze. Risparmia molto tempo.


1

Stavo riscontrando questo problema perché stavo generando il mio EDMX da un database esistente (progettato da qualcun altro, e qui uso il termine "progettato" liberamente).

Si scopre che il tavolo non aveva chiavi. EF stava generando il modello con molti tasti multipli. Ho dovuto aggiungere una chiave primaria alla tabella db in SQL e quindi aggiornato il mio modello in VS.

Ciò ha risolto il problema per me.


1

Questa non è una nuova risposta, ma aiuterà qualcuno che non è sicuro di come impostare la chiave primaria per la propria tabella. Usalo in una nuova query ed esegui. Ciò imposterà la colonna UniqueID come chiave primaria.

USE [YourDatabaseName]
GO

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

1

inserisci qui la descrizione dell'immagine

Nel mio caso, ho dimenticato di definire la chiave primaria per la tabella. Quindi assegna come mostrato in Figura e aggiorna la tabella da "Aggiorna modello dal database" dal file .edmx. Spero che ti sia d'aiuto !!!


0

L'aggiunta della chiave primaria ha funzionato anche per me!

Fatto ciò, ecco come aggiornare il modello di dati senza eliminarlo -

Fare clic con il tasto destro sulla pagina di progettazione edmx Entity e "Aggiorna modello dal database".


0

Sfortunatamente ho avuto lo stesso identico problema, l'aggiunta della chiave primaria non risolve il problema. Quindi ecco come risolvo il mio:

  1. Assicurati di avere a primary keysul tavolo in modo da modificare la mia tabella e aggiungere una chiave primaria.
  2. Delete the ADO.NET Entity Data Model (file edmx) dove utilizzo per mappare e connettermi con il mio database.
  3. Add again a new file of ADO.NET Entity Data Model per connettermi con il mio database e per mappare le proprietà del mio modello.
  4. Clean and rebuild the solution.

Problema risolto.


0

basta aggiungere una chiave primaria alla tabella e quindi ricreare il tuo EF


0

Ho dovuto solo rimuovere la tabella dal modello e aggiornare nuovamente il modello riportando la tabella. Immagino che la chiave primaria sia stata creata dopo che la tabella è stata inserita nel modello.


0

Ho riscontrato questo problema e credo che sia stato causato perché avevo eliminato l'Indice sulla chiave primaria delle mie tabelle e l'avevo sostituito con un indice su alcuni degli altri campi della tabella.

Dopo aver eliminato l'indice della chiave primaria e aggiornato edmx, gli inserti hanno smesso di funzionare.

Ho aggiornato la tabella alla versione precedente, aggiornato edmx e tutto funziona di nuovo.

Dovrei notare che quando ho aperto EDMX per risolvere questo problema, controllando per vedere se era stata definita una chiave primaria, c'era. Quindi nessuno dei suggerimenti di cui sopra mi stava aiutando. Ma l'aggiornamento dell'indice sulla chiave primaria sembrava funzionare.


0

Apri il tuo file .edmx nell'editor XML, quindi rimuovi il tag dal tag e cambia anche l'archivio: Schema = "dbo" in Schema = "dbo" e ricostruisci la soluzione ora l'errore si risolverà e sarai in grado di salvare i dati.


0

Ho trovato la risposta originale dell'aggiornamento del file .edmx che funziona meglio nella mia situazione. Non ero troppo felice di modificare il modello ogni volta che veniva aggiornato dal database. Ecco perché ho scritto un ulteriore file di modello di testo, che viene richiamato automaticamente quando il modello è cambiato, proprio come le entità sono appena generate. Lo inserisco qui in questo commento. Per farlo funzionare, assicurati di chiamarlo come {nome modello} .something.tt e archiviarlo nella stessa cartella della cartella .edmx. L'ho chiamato {nome modello} .NonPkTables.tt. Non genera un file da solo a causa della definizione di estensione del file non valida nella seconda riga. Sentiti libero di usare.

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ output extension="/" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq"#>
<#@ assembly name="%VS120COMNTOOLS%..\IDE\EntityFramework.dll" #>
<#@ assembly name="%VS120COMNTOOLS%..\IDE\Microsoft.Data.Entity.Design.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Windows.Forms" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Data.Entity.Core.Metadata.Edm" #>
<#@ import namespace="System.Data.Entity.Core.Mapping" #>
<#@ import namespace="System.CodeDom" #>
<#@ import namespace="System.CodeDom.Compiler" #>
<#@ import namespace="Microsoft.CSharp"#>
<#@ import namespace="System.Text"#>
<#@ import namespace="System.Diagnostics" #>

<#
    string modelFileName= this.Host.TemplateFile.Split('.')[0] + ".edmx";
    string edmxPath = this.Host.ResolvePath( modelFileName );

    // MessageBox.Show( this.Host.TemplateFile + " applied." );
    var modelDoc = XDocument.Load(edmxPath);
    var root = modelDoc.Root;
    XNamespace nsEdmx = @"http://schemas.microsoft.com/ado/2009/11/edmx";
    XNamespace ns = @"http://schemas.microsoft.com/ado/2009/11/edm/ssdl";

    var runtime = root.Elements(nsEdmx + "Runtime").First();
    var storageModels = runtime.Elements(nsEdmx + "StorageModels").First();
    XNamespace nsStore = @"http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator";

    var schema = storageModels.Elements(ns + "Schema").First();
    XNamespace nsCustomAnnotation = @"http://schemas.microsoft.com/ado/2013/11/edm/customannotation";

    var entityTypes = schema.Nodes().OfType<XComment>().Where(c => c.Value.Contains("warning 6002: The table/view"));
    bool changed = false;

    foreach (var node in entityTypes)
    {
        var element = node.ElementsAfterSelf().First();
        string entityName = element.Attribute("Name").Value;

        // Find EntitySet in EntityContainer.
        var entityContainer = schema.Elements(ns + "EntityContainer").First();
        var entitySet = entityContainer.Elements(ns + "EntitySet").First(s => s.Attribute("Name").Value == entityName);

        // Change "store:Schema" attribute to "Schema" attribute.
        var attribute = entitySet.Attribute(nsStore + "Schema");

        if (attribute != null)
        {
            string schemaName = entitySet.Attribute(nsStore + "Schema").Value;
            entitySet.Attribute(nsStore + "Schema").Remove();
            entitySet.Add(new XAttribute("Schema", schemaName));
            changed |= true;
        }

        // Remove the DefiningQuery element.
        var definingQuery = entitySet.Element(ns + "DefiningQuery");

        if (definingQuery != null)
        {
            definingQuery.Remove();
            changed |= true;        
            Debug.WriteLine(string.Format("Removed defining query of EntitySet {0}.", entityName));
        }
    }

    if (changed)
        modelDoc.Save(edmxPath);
#>

-1

Ho riscontrato lo stesso messaggio di errore per inserire un record in una tabella con relazione Many-to-Many . Lo schema del mio database era:

Student (Id , Name)
Course (Code , Title),
Student-Course (Student_ID, Course_Code)

Tabella Studente e Corso hanno chiavi primarie Id e codice , rispettivamente , mentre il tavolo Student-Corso ha due chiavi esterne mappati con tavoli e per gli studenti del corso.

Logicamente, lo schema è corretto ma stavo commettendo un errore nel database, perché ogni tabella dovrebbe avere una chiave primaria.

La mia definizione sql per Student-Course era:

CREATE TABLE [dbo].[Student-Course] (
    [StudentID]  VARCHAR (12) NOT NULL,
    [CourseCode] VARCHAR (10) NOT NULL,
    CONSTRAINT [FK_Student-Course_ToCourse] FOREIGN KEY ([Course_Code]) REFERENCES [dbo].[Course] ([Code]) ON DELETE CASCADE,
    CONSTRAINT [FK_Student-Course_ToStudent] FOREIGN KEY ([Student_ID]) REFERENCES [dbo].[Student] ([Id]) ON DELETE CASCADE
);

Ho reso la coppia di chiavi esterne la chiave primaria di questa tabella e aggiornata a:

CREATE TABLE [dbo].[Student-Course] (
    [StudentID]  VARCHAR (12) NOT NULL,
    [CourseCode] VARCHAR (10) NOT NULL,
    CONSTRAINT [PK_Student-Course] PRIMARY KEY CLUSTERED ([Student_ID] ASC, [Course_Code] ASC),
    CONSTRAINT [FK_Student-Course_ToCourse] FOREIGN KEY ([Course_Code]) REFERENCES [dbo].[Course] ([Code]) ON DELETE CASCADE,
    CONSTRAINT [FK_Student-Course_ToStudent] FOREIGN KEY ([Student_ID]) REFERENCES [dbo].[Student] ([Id]) ON DELETE CASCADE
);

Spero che risolva i problemi per alcuni ragazzi.


Questa domanda ha già troppe risposte. Inoltre, quasi ogni risposta dice: "aggiungere una chiave primaria" e uno lo fa nel contesto di molti-a-molti.
Gert Arnold,

Hai ragione, ma alcune persone aggiungono un ID chiave primaria extra nella terza tabella, il che non è un buon approccio.
Summar Raja

Come dice anche l'altra risposta.
Gert Arnold,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.