Entity Framework: birincil anahtarsız tablo


165

Kullanarak yeni bir uygulama oluşturmak istiyorum mevcut bir DB var EF4.0

Bazı tablolarda birincil anahtarlar tanımlanmadı, böylece yeni bir Varlık Veri Modeli oluşturduğumda aşağıdaki iletiyi alıyorum:

The table/view TABLE_NAME does not have a primary key defined 
and no valid primary key could be inferred. This table/view has 
been excluded. To use the entity, you will need to review your schema, 
add the correct keys, and uncomment it.

Bunları kullanmak ve verileri değiştirmek istiyorsam, mutlaka bu tablolara bir PK eklemem gerekir mi, yoksa bir geçici çözüm var mı?


21
Joe Celko'dan alıntı yapmak için: birincil anahtarı yoksa, tablo değildir . Neden herkes birincil anahtar olmadan "normal" bir tablo oluşturmak istiyorsunuz? Sadece bu PK'yi ekleyin! Onlara ihtiyacınız olacak - daha erken değil ....
marc_s

4
Onun bir baktığımızda, bu HAVA Bu durumda görüntülerseniz stackoverflow.com/a/10302066/413032
Davut Gürbüz

50
Her tablonun birincil anahtara ihtiyaç duymayacağı tamamen geçerlidir. Genellikle yararlı değil, geçerli. EF'i karıştırmak iyi bir nedendir, çok fazla şey gerektirmez. ;-).
Suncat2000

25
Şirketimdeki DB yapısını değiştiremediğimi ve tablo yapısını değiştirmeyecek biri tarafından oluşturulduğunu hayal edin, bu senaryo mümkündür.
Tito

4
Burası tam olarak bulunduğumuz yer. Birincil anahtarı olmayan 3. taraf bir Oracle veritabanıyla çalışmak zorundayız.
David Brower

Yanıtlar:


58

Hata, tam olarak söylediği anlamına gelir.

Bu sorunu çözebilsen bile, bana güven, istemiyorsun. Tanıtılabilecek kafa karıştırıcı hataların sayısı şaşırtıcı ve korkutucu, performansınızın muhtemelen tüplerden aşağı ineceğinden bahsetmiyoruz.

Bu sorunu çözmeyin. Veri modelinizi düzeltin.

EDIT: Bir çok insanın bu soruyu küçümsediğini gördüm. Bu iyi, sanırım, ancak OP'nin bir tabloyu bir görünüm değil, birincil anahtar olmadan eşleştirmek istediğini unutmayın . Cevap hala aynı. EF'in masalarda PK olması gerektiği konusunda çalışmak, yönetilebilirlik, veri bütünlüğü ve performans açısından kötü bir fikirdir.

Bazıları, bir üçüncü taraf uygulamayla eşleştiklerinden, temeldeki veri modelini düzeltme yeteneğine sahip olmadıklarını yorumladı. Model sizin altınızdan değişebileceği için bu iyi bir fikir değil. Muhtemelen, bu durumda, yine OP'nin istediği olmayan bir görünüme eşlemek istersiniz.


44
Yaygın senarioslarda katılıyorum, ancak LOG tablosu gibi nadir senariolarda sadece ASAP kayıtları eklemeniz gerekiyor. PK olması, benzersizliği ve dizine ekleme işlemini kontrol ederken bir sorun olabilir. Ayrıca PK'nız KİMLİK ise, oluşturulan değeri EF'e döndürmek başka bir sorundur. bunun yerine GUID mi kullanıyorsunuz? üretim zamanı ve indeksleme / sıralama başka bir konudur! ... Peki bazı kritik OLTP senarios (Logging gibi) PK yok bir nokta ve olumlu bir noktaya sahip olmak!
Mahmud Moravej

5
@MahmoudMoravej: Öncelikle, kümeleme dizinleri ve birincil anahtarların fikirlerini karıştırmayın. Aynı şey değiller. IDENTITY sütunlarında kümelenmiş göstergeleri olan tablolarda çok yüksek performanslı ekler ekleyebilirsiniz. Dizin bakımı ile ilgili sorunlarla karşılaşırsanız, tabloyu düzgün bir şekilde bölümlendirmelisiniz. Kümelenmiş dizin içermeyen bir tabloyu bırakmak, sildikten sonra alanı geri kazanmak için etkili bir şekilde birleştiremeyeceğiniz anlamına da gelir. Endeksleri yoksa günlük tablonuzu sorgulamaya çalışan fakir kişinin üzücü.
Dave Markle

149
"Veri modelinizi düzeltin" gerçek bir cevap değil. Bazen yaratmadığımız ve değiştiremeyeceğimiz idealden az durumlarla yaşamak zorundayız. Ve @Colin'in dediği gibi, OP'nin tam olarak ne istediğini yapmanın bir yolu var.
TheSmurf

13
EF'yi karşılamak için kodun değiştirilmesi kendi başına bir çözümdür. Tüm tabloların birincil bir anahtara ihtiyacı yoktur ve zorlanmaları da gerekmez. Örneğin, bir Konunuz var ve 0 veya daha fazla anahtar kelimesi var. Anahtar kelimeler tablosunun bir üst konu kimliği ve karşılık gelen bir anahtar kelimesi olabilir. EF beni zorladığı için DB benim yeniden düzenlemeye ihtiyacım olduğunu söylemek için topal.
Aralık'ta Mrchief

14
Bu soruya cevap verilmemesi gerektiği için indirilmelidir. Sıklıkla değiştirilemeyen üçüncü taraf veritabanlarıyla çalışmamız gerekir.
Kurren

104

Bence bu Tillito tarafından çözüldü:

Entity Framework ve SQL Server Görünümü

Aşağıda onun girişini alıntılayacağım:

Aynı sorunu yaşadık ve çözüm şu:

Varlık çerçevesini birincil anahtar olarak bir sütun kullanmaya zorlamak için ISNULL kullanın.

Varlık çerçevesini bir sütunu birincil anahtar olarak kullanmamaya zorlamak için NULLIF kullanın.

Bunu uygulamanın kolay bir yolu, görünümünüzün select deyimini başka bir seçime sarmaktır.

Misal:

SELECT
  ISNULL(MyPrimaryID,-999) MyPrimaryID,
  NULLIF(AnotherProperty,'') AnotherProperty
  FROM ( ... ) AS temp

yanıtladı 26 '10 at 17:00 tarafından Tillito


6
+1 Bu doğru cevap, mükemmel bir dünyada, tüm eski veritabanlarını referans bütünlüğüne sahip olacak şekilde değiştirmek harika olurdu, ama gerçekte bu her zaman mümkün değildir.
Dylan Hayes

9
Bunu tavsiye etmem. Paricular ISNULL kısmı. EF iki PK'yi aynı algılarsa, benzersiz kayıtları oluşturmayabilir ve bunun yerine paylaşılan bir nesneyi döndürebilir. Bu başıma daha önce geldi.
Todd

@Todd - MyPrimaryID NOT NULL sütunu ise bu nasıl olabilir?
JoeCool

@JoeCool, sadece boş olmadığı için benzersiz olduğu anlamına gelmez. "BU ÇÖZÜM ÇALIŞMALARINI ..." iptal ettim, çünkü hangi bağlamda kullanıldığına bakılmaksızın, benzersizlikten emin olabilirsiniz. Şimdi düşünmek rağmen, bir kayıt silinirse, bu etkin bir şekilde aşağıdaki kayıtları 'PK' değiştirecektir.
Todd

1
-1, çünkü bu kimlik kimliğinden yoksun bir tabloya eşleme ile başa çıkmak için Entity Framework / C # kodunu nasıl yapılandıracağınıza cevap vermez. Bazı üçüncü taraf yazılımlar (bazı nedenlerden dolayı) bu şekilde yazılır.
Andrew Gray

27

Bunları kullanmak ve verileri değiştirmek istiyorsam, mutlaka bu tablolara bir PK eklemem gerekir mi, yoksa bir geçici çözüm var mı?

Bu soruya ulaşan ve Entity Framework Core kullanan kişiler için, artık bu tablolara veya herhangi bir geçici çözüm yapmaya PK eklemek zorunda değilsiniz. EF Core 2.1'den beri yeni bir özellik Sorgu Türleri var

Sorgu türleri aşağıdakiler için kullanılmalıdır:

  • Geçici FromSql () sorguları için dönüş türü olarak sunuluyor.
  • Veritabanı görünümleriyle eşleme.
  • Birincil anahtarı tanımlanmamış tablolarla eşleme.
  • Modelde tanımlanan sorgularla eşleme.

Yani DBContext sadece tip aşağıdaki özellik eklemek DbQuery<T>yerine DbSet<T>aşağıdaki gibi. Tablo adınızın MyTable:

public DbQuery<MyTable> MyTables { get; set; }

1
EF Core kullanıyorsanız en iyi cevap!
Jay

17

Bileşik anahtarlar Entity Framework Fluent API ile de yapılabilir

public class MyModelConfiguration : EntityTypeConfiguration<MyModel>
{
     public MyModelConfiguration()
     {
        ToTable("MY_MODEL_TABLE");
        HasKey(x => new { x.SourceId, x.StartDate, x.EndDate, x.GmsDate });
        ...
     }
}

Bu tür bir 'manuel haritalama' durumunda, gösterdiğiniz gibi özel bir anahtar belirtmenin etkili olduğunu buldum; Buna ek olarak, bileşik bir anahtardan (bu yanıtta gösterildiği gibi) yararlanmadıysanız, doğal veya bileşik olmayan, ancak güvenilir olabilen çok özel anahtarlar için bir modelBuilder.Entity<T>()zincir çağrısını etiketleyebilirsiniz .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)benzersiz olmak (genellikle, her neyse.)
Andrew Gray

5

Benim durumumda, bir varlığı birincil anahtar içermeyen bir Görünüm ile eşlemem gerekti. Dahası, bu Görünümü değiştirmeme izin verilmedi. Neyse ki, bu görünümün benzersiz bir dize olan bir sütunu vardı. Benim çözümüm bu sütunu birincil anahtar olarak işaretlemekti:

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[StringLength(255)]
public string UserSID { get; set; }

Hile EF. Mükemmel çalıştı, kimse fark etmedi ... :)


hayır .. UserIDÖnce Kod yaklaşımını kullanırsanız sütun oluşturacaktır ..!
Deepak Sharma

1
EF'i aldatmadınız. Sadece Itentityfonksiyonu kapatma emri verdiniz . Temel olarak, eğer doğruysam, yine UserIDde sizin için PK olarak sütun oluşturacak , ancak UserIDyeni bir kayıt oluşturduğunuzda varsayılan olarak olduğu gibi otomatik olarak artmayacaktır . Ayrıca, yine de farklı değerler tutmanız gerekir UserID.
Celdor

1
@Seldor UserSID bir dizedir, asla "otomatik olarak artırılmaz". Bir tamsayı kimlik sütunu olsaydı, veritabanı Entity Framework yerine ekleme sırasında arttıracaktır.
reggaeguitar

4

EF, veritabanında birincil anahtar gerektirmez. Eğer öyleyse, varlıkları görünümlere bağlayamazsınız.

Birincil anahtarınız olarak benzersiz bir alan belirtmek için SSDL'yi (ve CSDL) değiştirebilirsiniz. Eğer eşsiz bir alanınız yoksa, o zaman size güvendiğinize inanıyorum. Ama gerçekten eşsiz bir alanınız (ve PK'nız) olmalı, aksi takdirde daha sonra sorun yaşarsınız.

Erick


Bu ISNULL kesmek önler. Ancak duruma bağlı olarak başka yanıtlar gerekebilir - örneğin EF'deki bir PK için bazı veri türlerinin desteklenmediğini hissediyorum.
Todd

3

İşe yaramaz bir kimlik anahtarına sahip olmak bazen anlamsızdır. Kimlik kullanılmıyorsa, neden eklemeliyim? Ancak, Varlık bu konuda affedici değildir, bu nedenle bir kimlik alanı eklemek en iyisidir. Kullanılmasa bile, Entity'nin eksik kimlik anahtarı hakkındaki kesintisiz hatalarıyla uğraşmaktan daha iyidir.


3

BU ÇÖZÜM ÇALIŞMALARI

PK'niz olmasa bile manuel olarak eşlemenize gerek yoktur. EF'ye sütunlarınızdan birinin dizin olduğunu ve dizin sütununun boş bırakılamayacağını söylemeniz yeterlidir.

Bunu yapmak için, aşağıdaki gibi isNull işleviyle görünümünüze bir satır numarası ekleyebilirsiniz.

select 
    ISNULL(ROW_NUMBER() OVER (ORDER BY xxx), - 9999) AS id
from a

ISNULL(id, number) burada kilit nokta, EF'e bu sütunun birincil anahtar olabileceğini söylüyor


2
ISNULL bölümünü olsa tavsiye etmem. EF iki PK'yi aynı algılarsa, benzersiz kaydı oluşturmayabilir ve bunun yerine paylaşılan bir nesneyi döndürebilir. Bu başıma daha önce geldi.
Todd

1
İsnull kullanmanız gerekir, aksi takdirde EF null değerinin kullanılamayacağına inanmaz.
Archlight

2

Gerçekten bir PK'niz yoksa yukarıdaki cevaplar doğrudur.

Ama biri varsa ama sadece DB bir dizin ile belirtilmemişse ve DB değiştiremezsiniz (evet, Dilbert'in dünyasında çalışıyorum) anahtar olarak alan (lar) elle eşleştirebilirsiniz.


2

Bu sadece @Erick T'nin cevabına bir ektir. Benzersiz değerlere sahip tek bir sütun yoksa, geçici çözüm aşağıdaki gibi bir bileşik anahtar kullanmaktır:

[Key]
[Column("LAST_NAME", Order = 1)]
public string LastName { get; set; }

[Key]
[Column("FIRST_NAME", Order = 2)]
public string FirstName { get; set; }

Yine, bu sadece bir çözüm. Gerçek çözüm, veri modelini düzeltmektir.


2

Bu belki cevap vermek için geç ... ancak ...

Bir tablonun birincil anahtarı yoksa, EF'nin düzgün çalışması için analiz edilmesi gereken birkaç senaryo vardır. Kural şudur: EF, birincil anahtar içeren tablolar / sınıflarla çalışır. İzlemeyi böyle yapar ...

Diyelim ki tablonuz 1. Kayıtlar benzersizdir: benzersizlik tek bir yabancı anahtar sütunu ile yapılır: 2. Kayıtlar benzersizdir: benzersizlik birden çok sütunun birleşimi ile yapılır. 3. Kayıtlar benzersiz değildir (çoğunlukla *).

1. ve 2. senaryolar için DbContext modülüne OnModelCreating yöntemine aşağıdaki satırı ekleyebilirsiniz: modelBuilder.Entity (). HasKey (x => new {x.column_a, x.column_b}); // kayıtları benzersiz kılmak için gereken sayıda sütun.

3. senaryo için, tabloyu inceledikten sonra yukarıdaki çözümü (# 1 + # 2) kullanabilirsiniz (* tüm kayıtları benzersiz kılan şey). Tüm kayıtları benzersiz kılmak için TÜM sütunları eklemeniz gerekiyorsa, tablonuza birincil anahtar sütunu eklemek isteyebilirsiniz. Bu tablo, üçüncü taraf bir satıcıdan geliyorsa, birincil anahtar sütunu klon komut dosyanızdan isteğe bağlı olarak eklenmiş olarak bu tabloyu yerel veritabanınıza klonlayın (bir gecede veya ihtiyaç duyduğunuz kadar zaman).


1
  1. Tablo yapısını değiştirin ve Birincil Sütun ekleyin. Modeli Güncelle
  2. XML Editör'de .EDMX dosyasını değiştirin ve bu tablo için etiketin altına Yeni Sütun eklemeyi deneyin (ÇALIŞMAYACAKTIR)
  3. Çıkmak için yeni bir Birincil Sütun oluşturmak yerine, varolan tüm sütunları dahil ederek bileşik bir anahtar yapacağım ( WORKED )

Varlık Çerçevesi: Varlık Modeline Birincil Anahtar olmadan DataTable Ekleme.


EF 4.0 ile kompozit anahtar yaklaşımı denedim ve işe yaramadı.
Ralph Willgoss

Bu yaklaşım benim için mükemmel çalıştı, eski sistemlerle "bazen" çalışan bir acı olabilir ...
pinmonkeyiii

1

@CodeNotFound'un yanıtına güncelleyin .

EF Core 3.0'da DbQuery<T>kullanımdan kaldırıldı, bunun yerine aynı şeyi yapan Anahtarsız varlık türlerini kullanmalısınız . Bunlar ModelBuilder HasNoKey()yöntemiyle yapılandırılır . DbContext sınıfınızda bunu yapın

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<YourEntityType>(eb =>
        {
            eb.HasNoKey();
        });

}

Bununla birlikte, özellikle kısıtlamalar vardır:

  • DbContext'teki değişiklikler için hiçbir zaman izlenmez ve bu nedenle veritabanına hiçbir zaman eklenmez, güncellenmez veya silinmez.
  • Yalnızca navigasyon eşleme özelliklerinin bir alt kümesini destekler, özellikle:
    • Bir ilişkinin asıl sonu olarak asla hareket edemezler.
    • Sahip olunan kuruluşlarda gezinmeleri olmayabilir
    • Yalnızca normal varlıkları işaret eden referans gezinme özelliklerini içerebilirler.
    • Varlıklar, anahtarsız varlık türlerinde gezinme özellikleri içeremez.

Bu şu soru için

Bunları kullanmak ve verileri değiştirmek istiyorsam, mutlaka bu tablolara bir PK eklemem gerekir mi, yoksa bir geçici çözüm var mı?

Verileri bu şekilde değiştiremezsiniz - ancak okuyabilirsiniz. Verileri değiştirmek için başka bir yol (ör. ADO.NET, Dapper) kullanılması düşünülebilir - bu, nadiren okuma işlemi yapmamanız gereken ve çoğu durumda çoğu durumda EF Core'a bağlı kalmak istediğiniz durumlarda bir çözüm olabilir.

Ayrıca, gerçekten yığın (anahtarsız) tablolara ihtiyacınız varsa / çalışmak istiyorsanız - EF'i atmayı düşünün ve veritabanınızla konuşmak için başka bir yol kullanın.


0

Pratik bir bakış açısından, her tablonun - hatta depo masası gibi denormalize bir tablonun - birincil anahtarı olmalıdır. Ya da başarısız olursa, en azından benzersiz, boş olmayan bir dizine sahip olmalıdır.

Bir tür benzersiz anahtar olmadan, tabloda hem ORM katmanları hem de verilerin temel anlaşılması için çok sorunlu olan yinelenen kayıtlar görünebilir (ve görünecektir). Yinelenen kayıtları olan bir tablo muhtemelen kötü tasarımın bir belirtisidir.

En azından, tablonun en azından bir kimlik sütunu olması gerekir. Otomatik oluşturulan kimlik sütunu eklemek SQL Server'da yaklaşık 2 dakika ve Oracle'da 5 dakika sürer. Bu ekstra çaba için birçok problemden kaçınılacaktır.


Uygulamam bir veri ambarı ayarında (Oracle ile) ve beni bir dizin eklemek için 5 dakika boyunca ikna ettiniz. Gerçekten sadece 5 dakika sürer (veya bakmanız veya ETL'leri değiştirmeniz gerekiyorsa biraz daha fazla ).
Trent

0

Bu sorunla da karşılaştık ve null değerine sahip bir sütun varken önemli olan, null değerine sahip olmayan bağımlı bir sütunun olması ve bu iki sütunun birleşiminin benzersiz olmasıydı.

Bu yüzden Pratap Reddy tarafından verilen cevabı belirtmek bizim için iyi çalıştı.




-8

Tablonun yalnızca null değerlerine izin vermeyen bir sütunu olması gerekir

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.