Tidak dapat memperbarui EntitySet - karena ia memiliki elemen DefiningQuery dan tidak ada elemen <UpdateFunction>

534

Saya menggunakan Entity Framework 1 dengan .net 3.5.

Saya melakukan sesuatu yang sederhana seperti ini:

var roomDetails = context.Rooms.ToList();

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

Saya mendapatkan kesalahan ini ketika saya mencoba melakukan:

 context.SaveChanges();

Saya mendapatkan kesalahan:

Tidak dapat memperbarui EntitySet - karena ia memiliki elemen MendefinisikanQuery dan tidak ada elemen <UpdateFunction> dalam elemen <ModificationFunctionMapping> untuk mendukung operasi saat ini.

Saya melakukan banyak pembaruan pada konteksnya dan tidak memiliki masalah, itu hanya ketika saya mencoba untuk memperbarui entitas tertentu ini.

Semua pencarian saya menunjukkan hal yang sama, bahwa tidak ada kunci primer yang dinyatakan pada entitas yang saya coba perbarui. Tapi sayangnya, saya memiliki kunci primer yang dinyatakan ...

iKode
sumber
61
Saya membuat kesalahan, tidak ada kunci utama yang diatur di atas meja, terima kasih atas waktu Anda! Maaf untuk ketidaknyamanannya!
iKode
1
Kebetulan saya - mungkin membuat 1000 tabel dengan kunci utama, dan lupa satu - pesan pengecualian tidak banyak membantu
Peter Munnings
1
luar biasa. benar-benar saya lupa menambahkan kunci utama ke Tabel. Mari kita berusaha untuk berhati-hati)
AEMLoviji

Jawaban:

1024

Ini biasanya terjadi karena salah satu alasan berikut:

  • Set Entity dipetakan dari tampilan Database
  • Permintaan Database kustom
  • Tabel database tidak memiliki kunci utama

Setelah melakukannya, Anda mungkin masih perlu memperbarui dalam desainer Entity Framework (atau menghapus entitas dan kemudian menambahkannya) sebelum Anda berhenti mendapatkan kesalahan.

Ladislav Mrnka
sumber
2
Pastikan juga mengubah toko: Skema menjadi Skema hanya untuk EntitySet itu, jika Anda masih mengalami masalah.
Geoff
53
Kemudian hapus dan buat kembali entitas tersebut karena pembaruan tidak berfungsi dengan baik di perancang EF.
Suncat2000
48
PK adalah jawabannya. Terima kasih!
nrod
1
Pembaruan di desainer EF bekerja dengan baik untuk saya setelah menambahkan Kunci Utama ke basis data. Menggunakan EF 5.0 dan .net 4.0
StillLearnin
1
Sama disini ! Thx ... harus menghapus tabel dan kembali menambahkan ke EF untuk mengambilnya
ajzeffer
90

Cukup Tambahkan kunci utama ke tabel. Itu dia. Masalah terpecahkan.

ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
Jebastin J
sumber
13
dan jangan lupa klik "Perbarui Model dari Database" pada file .edmx Anda
Bashar Abu Shamaa
@BasharAbuShamaa jawaban ini tidak valid tanpa detail itu.
Kehlan Krumme
66

Inilah yang terjadi pada saya. Cukup menghapus mengakibatkan kesalahan lain. Saya mengikuti langkah-langkah posting ini kecuali yang terakhir. Demi kenyamanan Anda, saya menyalin 4 langkah dari pos yang saya ikuti untuk menyelesaikan masalah sebagai berikut:

  1. Klik kanan pada file edmx, pilih Buka dengan, editor XML
  2. Temukan entitas di edmx: elemen StorageModels
  3. Buang seluruhnya DefiningQuery
  4. Ganti nama store:Schema="dbo"menjadi Schema="dbo"(jika tidak, kode akan menghasilkan kesalahan yang mengatakan nama tidak valid)
kavitha Reddy
sumber
Terima kasih banyak - inilah yang memperbaiki masalah saya. Cukup mengganggu bahwa ini belum diperbaiki di EF. Dan, sangat menakjubkan bahwa Anda mengetahui hal ini!
Sepeda Dave
Saya mencoba menghapus entitas dan menambahkannya kembali. Kompilasi ulang. Pembersihan. Tidak ada yang berhasil untuk saya kecuali ini.
vintastic
1
Ini menyelesaikan masalah saya, namun saya tidak tahu bagaimana Anda mendapatkan jawaban dan mengapa saran Anda menyelesaikan masalah.
kerajinan
Apa yang terjadi jika Anda perlu memperbarui model basis data? Saya melakukan "Pembaruan Model dari Database" dan itu meninggalkan model saya sama sekali tidak dapat digunakan. Saya harus membatalkan dan memulai lagi. Jika ada cara mengatasinya?
Gary
Itu masalah yang sangat aneh. Apakah ada informasi tentang bagaimana masalah ini terjadi untuk menghindarinya? Meskipun demikian - itu membantu
r3dst0rm
41

Harap perhatikan bahwa mungkin Entitas Anda memiliki kunci utama tetapi tabel Anda di basis data tidak memiliki kunci utama .

Majid
sumber
1
Bagaimana mengatasinya, jika kita tidak dapat mengubah tabel database?
Kai Hartmann
Jika Anda dapat mengubah tabel DB untuk memiliki kunci utama maka pembuat kode akan berhenti membuat kesalahan yang sama, menghapus kunci dari EF akan menyebabkan banyak masalah lainnya.
Chris Schaller
30

UPDATE: Saya mendapatkan beberapa upvotes tentang ini akhir-akhir ini, jadi saya pikir saya akan membiarkan orang tahu saran saya berikan di bawah ini bukan yang terbaik. Karena saya awalnya mulai mengoceh tentang melakukan Entity Framework pada database keyless lama, saya menyadari bahwa hal terbaik yang dapat Anda lakukan DENGAN JAUH adalah melakukannya dengan membalikkan kode-terlebih dahulu. Ada beberapa artikel bagus tentang bagaimana melakukan ini. Cukup ikuti mereka, dan kemudian ketika Anda ingin menambahkan kunci untuk itu, gunakan anotasi data untuk "memalsukan" kunci tersebut.

Sebagai contoh, katakanlah saya tahu meja saya Orders, walaupun tidak memiliki kunci utama, dijamin hanya memiliki satu nomor pesanan per pelanggan. Karena itu adalah dua kolom pertama di atas tabel, saya akan menyiapkan kode kelas pertama agar terlihat seperti ini:

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

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

Dengan melakukan ini, Anda pada dasarnya memalsukan EF agar percaya bahwa ada kunci yang dikelompokkan yang terdiri dari OrderNumber dan Pelanggan. Ini akan memungkinkan Anda untuk melakukan sisipan, pembaruan, dll pada tabel tanpa kunci Anda.

Jika Anda tidak terlalu terbiasa melakukan reverse Code First, buka dan temukan tutorial yang bagus tentang Entity Framework Code First. Kemudian cari satu di Reverse Code First (yang melakukan Code First dengan database yang ada). Kemudian kembali saja ke sini dan lihat saran kunci saya lagi. :)

Jawaban asli :

Pertama: seperti yang orang lain katakan, opsi terbaik adalah menambahkan kunci utama ke tabel. Titik. Jika Anda dapat melakukan ini, jangan baca lagi.

Tetapi jika Anda tidak bisa, atau hanya membenci diri sendiri, ada cara untuk melakukannya tanpa kunci utama.

Dalam kasus saya, saya bekerja dengan sistem legacy (awalnya file datar pada AS400 porting ke Access dan kemudian porting ke T-SQL). Jadi saya harus mencari cara. Ini solusi saya. Berikut ini bekerja untuk saya menggunakan Entity Framework 6.0 (yang terbaru di NuGet pada tulisan ini).

  1. Klik kanan pada file .edmx Anda di Solution Explorer. Pilih "Buka Dengan ..." lalu pilih "Editor XML (Teks)". Kami akan mengedit kode yang dibuat secara otomatis di sini.

  2. Cari garis seperti ini:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. Hapus store:Name="table_name"dari ujung.

  4. Ubah store:Schema="whatever"keSchema="whatever"

  5. Lihat di bawah garis itu dan temukan <DefiningQuery>tag. Itu akan memiliki pernyataan pilih ol besar di dalamnya. Hapus tag dan isinya.

  6. Sekarang baris Anda akan terlihat seperti ini:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. Kami memiliki sesuatu yang lain untuk diubah. Buka file Anda dan temukan ini:
    <EntityType Name="table_name">

  8. Di dekatnya, Anda mungkin akan melihat beberapa teks yang dikomentari memperingatkan Anda bahwa itu tidak memiliki kunci utama yang diidentifikasi, sehingga kunci itu telah disimpulkan dan definisi adalah tabel / tampilan read-only. Anda dapat meninggalkannya atau menghapusnya. Saya menghapusnya.

  9. Di bawah ini adalah <Key>tag. Inilah yang akan digunakan oleh Entity Framework untuk melakukan penyisipan / perbarui / hapus. JADI PASTIKAN ANDA MELAKUKAN HAK INI. Properti (atau properti) dalam tag itu perlu menunjukkan baris yang dapat diidentifikasi secara unik. Sebagai contoh, katakanlah saya tahu meja saya orders, walaupun tidak memiliki kunci utama, dijamin hanya memiliki satu nomor pesanan per pelanggan.

Jadi milikku terlihat seperti:

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

Serius, jangan lakukan ini salah. Katakanlah meskipun tidak boleh ada duplikat, entah bagaimana dua baris masuk ke sistem saya dengan nomor pesanan dan nama pelanggan yang sama. Astaga! Itulah yang saya dapatkan karena tidak menggunakan kunci! Jadi saya menggunakan Entity Framework untuk menghapusnya. Karena saya tahu duplikat adalah satu-satunya pesanan yang dimasukkan hari ini, saya melakukan ini:

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

Tebak apa? Saya baru saja menghapus duplikat DAN yang asli! Itu karena saya mengatakan kepada Entity Framework bahwa order_number / cutomer_name adalah kunci utama saya. Jadi ketika saya mengatakannya untuk menghapus duplikat Order, apa yang dilakukan di latar belakang adalah sesuatu seperti:

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

Dan dengan peringatan itu ... Anda sekarang harus pergi dengan baik!

Pharylon
sumber
Menemukan jawaban ini setelah menemukan solusi yang sama untuk masalah tersebut. Jelas jawaban yang benar! Hanya mendefinisikan kunci utama seperti yang disebutkan dalam jawaban lain tidak akan membantu dalam banyak kasus.
Obl Tobl
19

Ini juga dapat terjadi jika model data ketinggalan zaman.

Semoga ini akan menyelamatkan orang lain frustrasi :)

mob1lejunkie
sumber
6

Saya mendapatkan pesan kesalahan yang sama, tetapi dalam skenario saya, saya mencoba memperbarui entitas yang berasal dari hubungan banyak-ke-banyak menggunakan PJT (Pure Join Table).

Dari membaca posting lain, saya pikir saya bisa memperbaikinya dengan menambahkan bidang PK tambahan ke tabel bergabung ... Namun, jika Anda menambahkan kolom PK ke tabel bergabung, itu bukan lagi PJT dan Anda kehilangan semua keuntungan kerangka kerja entitas seperti pemetaan hubungan otomatis antara entitas.

Jadi solusi dalam kasus saya adalah mengubah tabel join pada DB untuk membuat PK yang mencakup KEDUA kolom ID asing.

Kerry Randolph
sumber
Apakah ini cara menghasilkan EDMX selalu bekerja? Saya sudah terbiasa bekerja dengan Code First yang tidak memerlukan PK pada tabel join murni.
Michael Hornfeck
4

kesalahan dapat terjadi, jika tabel Anda tidak memiliki kunci utama, dalam hal ini tabelnya adalah "hanya baca", dan perintah db.SaveChanges () selalu akan membawa kesalahan

Ruben.sar
sumber
4

Atur Primary Key kemudian simpan Table dan Refresh kemudian pergi ke Table.edmx delete Table dan dapatkan lagi.

Ali Raza
sumber
3

jadi itu benar, cukup tambahkan kunci utama

Catatan: pastikan bahwa ketika Anda memperbarui diagram EF Anda dari basis data yang Anda tunjuk ke basis data yang tepat , dalam kasus saya string koneksi menunjuk ke DB lokal alih-alih Dev DB terbaru, anak sekolah kesalahan yang saya tahu, tetapi saya ingin memposting ini karena bisa sangat membuat frustasi jika Anda yakin Anda telah menambahkan kunci utama dan Anda masih mendapatkan kesalahan yang sama

laba laba
sumber
2

Saya memiliki masalah yang sama. Seperti kata utas ini, Meja saya tidak memiliki PK, jadi saya mengatur PK dan menjalankan kode. Namun sayangnya kesalahan datang lagi. Apa yang saya lakukan selanjutnya adalah, menghapus koneksi DB (menghapus file .edmx di folder Model Solution Explorer) dan membuatnya kembali. Kesalahan hilang setelah itu. Terima kasih semuanya telah berbagi pengalaman Anda. Ini menghemat banyak waktu.

Namal
sumber
1

Saya mendapatkan masalah ini karena saya menghasilkan EDMX saya dari database yang ada (dirancang oleh orang lain, dan saya menggunakan istilah 'dirancang' secara longgar di sini).

Ternyata meja tidak punya kunci sama sekali. EF menghasilkan model dengan banyak tombol. Saya harus menambahkan kunci utama ke tabel db di SQL dan kemudian memperbarui model saya di VS.

Itu memperbaikinya bagi saya.

Telanjang
sumber
1

Ini bukan jawaban baru tetapi akan membantu seseorang yang tidak yakin cara mengatur kunci utama untuk tabel mereka. Gunakan ini dalam kueri baru dan jalankan. Ini akan menetapkan kolom UniqueID sebagai kunci utama.

USE [YourDatabaseName]
GO

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

masukkan deskripsi gambar di sini

Dalam kasus saya, lupa mendefinisikan Kunci Utama ke Tabel. Jadi tetapkan seperti yang ditunjukkan pada Gambar dan Perbarui tabel Anda dari "Perbarui model dari Database" dari file .edmx Semoga ini bisa membantu !!!

Yogesh Dangre
sumber
0

Menambahkan kunci utama juga berfungsi untuk saya!

Setelah selesai, berikut ini cara memperbarui model data tanpa menghapusnya -

Klik kanan pada halaman desainer Entitas edmx dan 'Perbarui Model dari Database'.

Abhishek Poojary
sumber
0

Saya memiliki masalah yang sama persis, sayangnya, menambahkan kunci utama tidak menyelesaikan masalah. Jadi, inilah cara saya menyelesaikan masalah saya:

  1. Pastikan Anda memiliki primary keydi atas meja, jadi saya mengubah tabel saya dan menambahkan kunci utama.
  2. Delete the ADO.NET Entity Data Model (file edmx) tempat saya gunakan untuk memetakan dan terhubung dengan database saya.
  3. Add again a new file of ADO.NET Entity Data Model untuk terhubung dengan database saya dan untuk memetakan properti model saya.
  4. Clean and rebuild the solution.

Masalah terpecahkan.

Willy David Jr
sumber
0

cukup tambahkan kunci utama ke meja Anda dan buat ulang EF Anda

Sulyman
sumber
0

Saya hanya perlu menghapus tabel dari model dan memperbarui model lagi membawa tabel kembali. Saya kira kunci utama dibuat setelah tabel ditarik ke dalam model.

dangalg
sumber
0

Saya mengalami masalah ini dan percaya itu disebabkan karena saya telah menghapus Indeks pada kunci utama tabel saya dan menggantinya dengan indeks pada beberapa bidang lain dalam tabel.

Setelah saya menghapus indeks kunci utama dan menyegarkan edmx, sisipan berhenti berfungsi.

Saya me-refresh tabel ke versi yang lebih lama, me-refresh edmx dan semuanya berfungsi lagi.

Saya harus mencatat bahwa ketika saya membuka EDMX untuk memecahkan masalah ini, memeriksa untuk melihat apakah ada kunci primer yang ditentukan, ada. Jadi tidak ada saran di atas yang membantu saya. Tetapi menyegarkan indeks pada kunci utama sepertinya berhasil.

armstb01
sumber
0

Buka file .edmx Anda dalam editor XML dan kemudian hapus tag dari Tag dan juga ubah store: Schema = "dbo" ke Schema = "dbo" dan bangun kembali solusi sekarang kesalahan akan menyelesaikan dan Anda akan dapat menyimpan data.

Sharad Tiwari
sumber
0

Saya menemukan jawaban asli untuk memperbarui file .edmx paling baik dalam situasi saya. Saya hanya tidak terlalu senang mengubah model setiap kali itu diperbarui dari database. Itu sebabnya saya menulis file Template Teks tambahan, yang secara otomatis dipanggil ketika setelah model telah berubah - sama seperti entitas yang baru dibuat. Saya memposting di sini di komentar ini. Untuk membuatnya berfungsi, pastikan Anda menamainya seperti {model name} .something.tt, dan simpan di folder yang sama dengan folder .edmx Anda. Saya menamainya {nama model} .NonPkTables.tt. Itu tidak menghasilkan file sendiri karena definisi ekstensi file tidak valid di baris kedua. Jangan ragu untuk menggunakannya.

<#@ 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);
#>
Arno Tolmeijer
sumber
-1

Saya menghadapi pesan kesalahan yang sama untuk menyisipkan catatan di tabel yang memiliki hubungan Many-to-Many . Skema basis data saya adalah:

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

Tabel Student dan Course masing-masing memiliki ID dan Kode kunci utama , sedangkan tabel Student-Course memiliki dua kunci asing yang dipetakan dengan tabel Student dan Course.

Logikanya, skema sudah benar tetapi saya membuat kesalahan dalam Database, karena setiap tabel harus memiliki kunci utama.

Definisi sql saya untuk Kursus Siswa adalah:

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
);

Saya menjadikan sepasang kunci asing sebagai kunci utama tabel ini dan diperbarui ke:

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
);

Semoga ini bisa menyelesaikan masalah bagi sebagian cowok.

Summar Raja
sumber
Pertanyaan ini sudah memiliki terlalu banyak jawaban. Selain itu, hampir setiap jawaban mengatakan "tambahkan kunci utama" dan satu melakukannya dalam konteks banyak-ke-banyak.
Gert Arnold
Anda benar, tetapi beberapa orang menambahkan id kunci primer tambahan di tabel ketiga, yang bukan pendekatan yang baik.
Summar Raja
Seperti jawaban lain juga mengatakan.
Gert Arnold