EntitySet güncellenemiyor - çünkü bir DefiningQuery var ve <UpdateFunction> öğesi yok


534

Entity Framework 1'i .net 3.5 ile kullanıyorum.

Ben böyle basit bir şey yapıyorum:

var roomDetails = context.Rooms.ToList();

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

Yapmaya çalıştığımda bu hatayı alıyorum:

 context.SaveChanges();

Hatayı alıyorum:

EntitySet güncellenemiyor - çünkü bir DefiningQuery var ve mevcut işlemi desteklemek için <ModificationFunctionMapping> öğesinde <UpdateFunction> öğesi yok.

Bağlamda çok fazla güncelleme yapıyorum ve herhangi bir sorunum yok, sadece bu belirli varlığı güncellemeye çalıştığımda.

Tüm aramalarım aynı şeyi gösteriyor, güncellemeye çalıştığım varlıkta belirtilen birincil anahtar yok. Ama ne yazık ki, Birincil anahtarım var ...


61
Bir hata yaptım, masanın üzerinde birincil anahtar yoktu, zaman ayırdığınız için teşekkürler! Rahatsızlıktan dolayı özür dileriz!
iKode

1
Sadece başıma geldi - muhtemelen birincil anahtarlarla 1000 tablo oluşturdu ve birini unuttum - istisna mesajı pek yardımcı olmuyor
Peter Munnings

1
mükemmel. Gerçekten Tablo birincil anahtar eklemek unuttum. Dikkatli olmaya çalışalım)
AEMLoviji

Yanıtlar:


1023

Genellikle aşağıdaki nedenlerden biri nedeniyle olur:

  • Varlık Kümesi Veritabanı görünümünden eşlendi
  • Özel bir Veritabanı sorgusu
  • Veritabanı tablosunun birincil anahtarı yok

Bunu yaptıktan sonra, hatayı almayı bırakmadan önce Entity Framework tasarımcısında güncellemeniz (veya alternatif olarak varlığı silmeniz ve sonra eklemeniz) gerekebilir.


2
Ayrıca sorun yaşıyorsanız: Şema'yı yalnızca EntitySet için yalnızca Şema olarak değiştirdiğinizden emin olun.
Geoff

53
Ardından EF tasarımcısında güncelleme düzgün çalışmadığından varlığı silin ve yeniden oluşturun.
Suncat2000

48
PK cevaptı. Teşekkürler!
nrod

1
EF tasarımcısında güncelleme, veritabanına Birincil Anahtar ekledikten sonra benim için iyi çalıştı. EF 5.0 ve .net 4.0 kullanma
StillLearnin

1
Burada aynı ! Thx ... tabloyu kaldırmak ve yine de almak için EF eklemek zorunda kaldı
ajzeffer

90

Sadece tabloya birincil anahtar ekleyin. Bu kadar. Sorun çözüldü.

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

13
ve
.edmx

@BasharAbuShamaa bu cevap bu detay olmadan geçerli değil.
Kehlan Krumme

66

Benim için durum böyle. Kaldırılması başka bir hatayla sonuçlandı. Sonuncusu dışında bu yazının adımlarını izledim. Size kolaylık sağlamak için, sorunu çözmek için takip ettiğim 4 adımdan aşağıdaki adımı kopyaladım:

  1. Edmx dosyasına sağ tıklayın, Birlikte aç, XML düzenleyici'yi seçin
  2. Varlığı edmx: StorageModels öğesinde bulun
  3. DefiningQuery'yi tamamen kaldırın
  4. Kime adını store:Schema="dbo"değiştirin Schema="dbo"(aksi takdirde kod, adın geçersiz olduğunu belirten bir hata oluşturur)

Çok teşekkür ederim - sorunum tam olarak bu sorunu çözdü. Bunun EF'de düzeltilmemesi oldukça rahatsız edici. Ve bunu anlamanız oldukça şaşırtıcı!
Bisiklet Dave

Varlığı silmeyi ve yeniden eklemeyi denedim. Yeniden derlenerek. Temizlik. Bunun dışında benim için hiçbir şey işe yaramadı.
vintastic

1
Bu, sorunumu çözdü, ancak cevapları nasıl bulduğunuzu ve önerinizin sorunu neden çözdüğünü bilmiyorum.
swcraft

Veritabanı modelini güncellemeniz gerekirse ne olur? "Veritabanından Güncelleme Modeli" yaptım ve modelimi tamamen kullanılamaz hale getirdi. Geri almak ve baştan başlamak zorunda kaldım. Bunun etrafında bir yol varsa?
Gary

Bu gerçekten garip bir mesele. Bu sorunun önlenmesi için nasıl oluştuğuna dair herhangi bir bilgi var mı? Yine de - yardımcı oldu
r3dst0rm

41

Sadece o belki dikkat Varlık sahip birincil anahtar ancak veritabanında tablo yoktur birincil anahtar .


1
Veritabanı tablosunu değiştiremezsek nasıl üstesinden geliriz?
Kai Hartmann

DB tablosunu birincil bir anahtar olacak şekilde değiştirirseniz, kod oluşturucu aynı hataları yapmayı durduracak, anahtarı EF'den çıkarmak başka birçok soruna neden olacaktır.
Chris Schaller

30

GÜNCELLEME: Son zamanlarda bu konuda birkaç oy aldım, bu yüzden insanların aşağıda verdiğim tavsiyenin en iyi olmadığını bilmelerini sağladım. Başlangıçta eski anahtarsız veritabanlarında Entity Framework ile uğraşmaya başladığım için, BY FAR ile yapabileceğiniz en iyi şeyin ters kod ilk önce yapmak olduğunu fark ettim. Bunun nasıl yapılacağı hakkında birkaç iyi makale var. Onları takip edin ve sonra bir anahtar eklemek istediğinizde, anahtarı "taklit etmek" için veri ek açıklamalarını kullanın.

Örneğin, Ordersbirincil anahtar olmasa da, masamın bildiğini varsayalım , her müşteri için yalnızca bir sipariş numarasının olduğundan emin olabilirsiniz. Bunlar tablodaki ilk iki sütun olduğundan, kod ilk sınıflarını şöyle görünecek şekilde ayarladım:

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

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

Bunu yaparak, temelde EF'i OrderNumber ve Customer'dan oluşan kümelenmiş bir anahtar olduğuna inanarak taklit edersiniz. Bu, anahtarsız tablonuzda ekler, güncellemeler vb. Yapmanızı sağlar.

İlk önce Ters Kod yapmayı bilmiyorsanız, önce Entity Framework Kodu hakkında iyi bir öğretici bulun. Sonra ilk önce Ters Kod üzerinde bir tane bul (var olan bir veritabanıyla Kod İlk yapıyor). Sonra buraya geri dönün ve anahtar tavsiyeme tekrar bakın. :)

Orijinal Yanıt :

Birincisi: diğerlerinin söylediği gibi, en iyi seçenek tabloya birincil anahtar eklemektir. Tam durak. Bunu yapabiliyorsanız, daha fazla okuyun.

Ancak yapamıyorsanız veya sadece kendinizden nefret ediyorsanız, birincil anahtar olmadan bunu yapmanın bir yolu vardır.

Benim durumumda, eski bir sistemle çalışıyordum (aslen Access'e taşınan ve daha sonra T-SQL'e taşınan bir AS400'deki düz dosyalar). Bu yüzden bir yol bulmalıydım. Bu benim çözümüm. Aşağıdakiler benim için Entity Framework 6.0 (NuGet'in en sonuncusu).

  1. Solution Explorer'da .edmx dosyanızı sağ tıklatın. "Birlikte Aç ..." ı ve ardından "XML (Metin) Düzenleyicisi" ni seçin. Burada otomatik olarak oluşturulan kodu el ile düzenleyeceğiz.

  2. Bunun gibi bir çizgi arayın:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. Sondan çıkarın store:Name="table_name".

  4. Değişim store:Schema="whatever"içinSchema="whatever"

  5. Bu satırın altına bakın ve <DefiningQuery>etiketi bulun . İçinde büyük bir ol 'select deyimi olacaktır. Etiketi ve içeriğini kaldırın.

  6. Şimdi hattınız şöyle görünmelidir:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. Değiştirecek başka bir şeyimiz var. Dosyanızı gözden geçirin ve şunu bulun:
    <EntityType Name="table_name">

  8. Yakınlarda, birincil anahtarın tanımlanmadığına dair sizi uyaran bazı yorumlanmış metinler göreceksiniz, bu nedenle anahtar çıkartıldı ve tanım salt okunur bir tablo / görünümdür. Bırakabilir veya silebilirsiniz. Ben onu sildim.

  9. Aşağıda <Key>etiketi. Entity Framework'ün ekleme / güncelleme / silme işlemleri için kullanacağı şey budur. BU DOĞRU OLDUĞUNDAN EMİN OLUN. Bu etiketteki özellik (veya özellikler), benzersiz bir şekilde tanımlanabilir bir satırı göstermelidir. Örneğin, ordersbirincil anahtar olmasa da, masamın her müşteri için yalnızca bir sipariş numarasına sahip olduğundan emin olduğumu varsayalım.

Yani benimki şöyle görünüyor:

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

Cidden, bunu yanlış yapma. Diyelim ki asla kopya olmamasına rağmen, bir şekilde iki sıra aynı sipariş numarası ve müşteri adı ile sistemime giriyor. Whooops! Anahtar kullanmamaya çalıştığım şey bu! Bu yüzden birini silmek için Entity Framework kullanıyorum. Yinelenen bugün koymak tek sipariş olduğunu biliyorum, bunu yapmak:

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

Bil bakalım ne oldu? Ben sadece hem yinelenen VE orijinal sildi! Çünkü Entity Framework'e order_number / cutomer_name komutunun birincil anahtarım olduğunu söyledim. Yani duplicateOrder kaldırmak için söyledim, arka planda yaptığı gibi bir şeydi:

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

Ve bu uyarıyla ... şimdi gitmek için iyi olmalısın!


Soruna aynı çözümü bulduktan sonra bu cevabı buldum. Kesinlikle doğru cevap! Yalnızca diğer yanıtlarda belirtildiği gibi birincil anahtar tanımlamak çoğu durumda yardımcı olmaz.
Obl Tobl

19

Bu, veri modeli güncel değilse de olabilir.

Umarım bu başka birinin hayal kırıklığını kurtaracaktır :)


6

Aynı hata iletisini alıyordum, ancak senaryomda PJT (Pure Join Table) kullanarak çoktan çoğa ilişkiden türetilmiş varlıkları güncellemeye çalışıyordum.

Diğer yazıları okuduğumda, birleştirme tablosuna ek bir PK alanı ekleyerek düzeltebileceğimi düşündüm ... Ancak, bir birleştirme tablosuna PK sütunu eklerseniz, artık bir PJT değildir ve tüm varlıklar arasındaki otomatik ilişki eşlemesi gibi varlık çerçevesi avantajları.

Benim durumumda çözüm, yabancı kimlik sütunları İKİ içeren bir PK yapmak için DB birleştirme tablosunu değiştirmek oldu.


EDMX oluşturmak hep böyle mi çalıştı? Saf bir birleşim tablosunda bir PK gerektirmeyen Code First ile çalışmaya alışkınım.
Michael Hornfeck

4

tablonuzda birincil anahtar yoksa bir hata oluşabilir, bu durumda tablo "salt okunur" db.SaveChanges () komutu her zaman bir hata getirir


4

Birincil Anahtarı ayarlayın, ardından Tabloyu ve Yenile'yi kaydedin ve Model.edmx Tabloyu sil'e gidin ve tekrar alın.


3

bu yüzden doğru, sadece birincil anahtar ekleyin

Not: EF diyagramınızı doğru veritabanına işaret ettiğiniz veritabanından güncellerken, benim durumumda bağlantı dizesinin, güncel Dev DB, okul çocuğu yerine yerel bir DB'yi işaret ettiğinden emin olun hata biliyorum, ama bunu göndermek istedim çünkü birincil anahtarı eklediğinize ve hala aynı hatayı alıyorsanız ikna ederseniz çok sinir bozucu olabilir


2

Aynı sorunu yaşadım. Bu iş parçacığının dediği gibi, Masamın bir PK'si yoktu, bu yüzden PK'yi ayarladım ve kodu çalıştırdım. Ancak maalesef hata tekrar geldi. Daha sonra yaptığım, DB bağlantısını sildi (Solution Explorer'ın Model klasöründeki .edmx dosyasını silin) ​​ve yeniden yarattı. Bundan sonra hata gitti. Deneyimlerinizi paylaştığınız için herkese teşekkürler. Çok zaman kazandırır.


1

Ben EDMX mevcut bir veritabanından (başka biri tarafından tasarlanan ve ben burada 'tasarlanmış' terimini gevşek burada) üreten çünkü ben bu sorunu alıyordu.

Tabii ki herhangi bir anahtar yoktu. EF modeli birçok anahtarla üretiyordu. SQL db tabloya birincil anahtar eklemek gitmek zorunda kaldı ve sonra VS modelimi güncelledi.

Bu benim için sorunumu çözdü.


1

Bu yeni bir cevap değil, ancak tabloları için birincil anahtarı nasıl ayarlayacağından emin olmayan birine yardımcı olacaktır. Bunu yeni bir sorguda kullanın ve çalıştırın. Bu, UniqueID sütununu birincil anahtar olarak ayarlar.

USE [YourDatabaseName]
GO

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

1

resim açıklamasını buraya girin

Benim durumumda, Tabloya Birincil Anahtar tanımlamayı unuttum. Resimde gösterildiği gibi atayın ve .edmx dosyasından "Veritabanından Modeli Güncelle" den tablonuzu yenileyin. Umarım yardımcı olur !!!


0

Birincil anahtarı eklemek benim için de işe yaradı!

Bu yapıldıktan sonra, veri modelini silmeden nasıl güncelleyeceğiniz aşağıda açıklanmıştır -

Edmx Entity tasarımcı sayfasına sağ tıklayın ve 'Modeli Veritabanından Güncelle'.


0

Aynı sorunu yaşadım, maalesef, birincil anahtarı eklemek sorunu çözmüyor. İşte benimkini şu şekilde çözüyorum:

  1. Masamda bir tane olduğundan emin olun, primary keyböylece masamı değiştirir ve birincil anahtar eklerim.
  2. Delete the ADO.NET Entity Data Model (edmx dosyası) burada veritabanımı eşleştirmek ve bağlanmak için kullanın.
  3. Add again a new file of ADO.NET Entity Data Model veritabanımla bağlantı kurmak ve model özelliklerimi eşleştirmek için.
  4. Clean and rebuild the solution.

Sorun çözüldü.


0

sadece masanıza birincil anahtar ekleyin ve EF'nizi yeniden oluşturun


0

Tabloyu modelden çıkarmak ve tekrar masaya getirerek modeli güncellemek zorunda kaldım. Sanırım birincil anahtar tablo modele çekildikten sonra oluşturuldu.


0

Bu sorunu geldi ve tablolarım birincil anahtarında dizin sildi ve tablodaki diğer alanların bazılarında bir dizin ile değiştirildi çünkü neden olduğuna inanıyorum vardı.

Birincil anahtar dizinini sildikten ve edmx'i yeniledikten sonra, ekler çalışmayı durdurdu.

Tabloyu eski sürüme, edmx'i yeniledim ve her şey tekrar çalışıyor.

Bu sorunu gidermek için EDMX'i açtığımda, tanımlanmış bir birincil anahtar olup olmadığını kontrol ettim. Yani yukarıdaki önerilerin hiçbiri bana yardımcı olmadı. Ancak birincil anahtardaki dizini yenilemek işe yaramış gibi görünüyordu.


0

.Edmx dosyanızı XML düzenleyicide açın ve etiketi Tag'den kaldırın ve ayrıca store'u değiştirin: Schema = "dbo" yerine Schema = "dbo" yapın ve çözümü şimdi yeniden oluşturun hatası çözülecek ve verileri kaydedebileceksiniz.


0

Durumumda en iyi iş .edmx dosyasını güncelleme orijinal cevabını buldum. Veritabanından her güncellendiğinde modeli değiştirmekten çok mutlu değildim. Bu yüzden, model değiştikten sonra otomatik olarak çağrılan ek bir Metin Şablonu dosyası yazdım - tıpkı objelerin yeni oluşturulduğu gibi. Bu yorumda buraya gönderiyorum. Çalışması için {model name} .something.tt gibi adlandırdığınızdan emin olun ve .edmx klasörünüzle aynı klasörde saklayın. Adı {model name} .NonPkTables.tt. İkinci satırdaki geçersiz dosya uzantısı tanımı nedeniyle kendi başına bir dosya oluşturmaz. Kullanmaktan çekinmeyin.

<#@ 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

Çok -çok ilişkisi olan bir tabloya kayıt eklemek için aynı hata iletisiyle karşılaştım . Veritabanı şemam şuydu:

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

Tablo Öğrenci ve Kursunda sırasıyla ID ve Kod birincil anahtarları bulunurken, Öğrenci-Kurs tablosunda Öğrenci ve Kurs tablolarıyla eşlenmiş iki Yabancı anahtar vardır.

Mantıksal olarak, şema doğrudur ama her tabloda birincil anahtar olması gerektiği için ben Veritabanı'nda bir hata yapıyordum.

Student-Course için sql tanımım :

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

Ben yabancı anahtar çifti bu tablonun birincil anahtarı yaptı ve için güncelledi:

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

Umarım bazı erkekler için sorunları çözer.


Bu sorunun zaten çok fazla cevabı var. Dahası, hemen hemen her cevap "birincil anahtar ekle" der ve biri bunu çoktan çoğa bağlamında yapar.
Gert Arnold

Haklısınız, ancak bazı insanlar üçüncü tabloya ekstra bir birincil anahtar kimliği ekliyor , bu iyi bir yaklaşım değil.
Summar Raja

Diğer cevabın da söylediği gibi.
Gert Arnold
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.