EF Kodu Önce “Geçersiz sütun adı 'Ayırıcı' 'ancak kalıtım yok


154

Veritabanımda SEntries adlı bir tablo var (aşağıdaki tablo CREATE deyimi bakın). Birincil anahtarı, birkaç yabancı anahtarı ve bu konuda özel bir şey yok. Veritabanımda buna benzer birçok tablo var, ancak bazı nedenlerden dolayı bu tablo EF Proxy Sınıfı'nda bir "Diskriminator" sütunu ile son buldu.

Sınıf C # olarak şöyle bildirilir:

public class SEntry
{
    public long SEntryId { get; set; }

    public long OriginatorId { get; set; }
    public DateTime DatePosted { get; set; }
    public string Message { get; set; }
    public byte DataEntrySource { get; set; }
    public string SourceLink { get; set; }
    public int SourceAppId { get; set; }
    public int? LocationId { get; set; }
    public long? ActivityId { get; set; }
    public short OriginatorObjectTypeId { get; set; }
}

public class EMData : DbContext
{
    public DbSet<SEntry> SEntries { get; set; }
            ...
    }

Bu tabloya yeni bir satır eklemeye çalıştığımda hatayı alıyorum:

System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'.

Bu sorun yalnızca C # sınıfınızı başka bir sınıftan miras alıyorsanız oluşur, ancak SEntry hiçbir şeyden miras kalmaz (yukarıda gördüğünüz gibi).

Buna ek olarak, bir kez ben SEntries özelliği için EMData örneği üzerinde fare hata ayıklayıcı araç ipucu almak, görüntüler:

base {System.Data.Entity.Infrastructure.DbQuery<EM.SEntry>} = {SELECT 
[Extent1].[Discriminator] AS [Discriminator], 
[Extent1].[SEntryId] AS [SEntryId], 
[Extent1].[OriginatorId] AS [OriginatorId], 
[Extent1].[DatePosted] AS [DatePosted], 
[Extent1].[Message] AS [Message], 
[Extent1].[DataEntrySource] AS [DataE...

Bu sorunun en altına nereden ulaşılacağı konusunda herhangi bir öneriniz veya fikriniz var mı? Tabloyu, birincil anahtarı ve birkaç şeyi yeniden adlandırmayı denedim, ancak hiçbir şey çalışmıyor.

SQL Tablo:

CREATE TABLE [dbo].[SEntries](
[SEntryId] [bigint] IDENTITY(1125899906842624,1) NOT NULL,
[OriginatorId] [bigint] NOT NULL,
[DatePosted] [datetime] NOT NULL,
[Message] [nvarchar](500) NOT NULL,
[DataEntrySource] [tinyint] NOT NULL,
[SourceLink] [nvarchar](100) NULL,
[SourceAppId] [int] NOT NULL,
[LocationId] [int] NULL,
[ActivityId] [bigint] NULL,
[OriginatorObjectTypeId] [smallint] NOT NULL,
CONSTRAINT [PK_SEntries] PRIMARY KEY CLUSTERED 
(
[SEntryId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,       ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[SEntries]  WITH CHECK ADD  CONSTRAINT [FK_SEntries_ObjectTypes] FOREIGN KEY([OriginatorObjectTypeId])
REFERENCES [dbo].[ObjectTypes] ([ObjectTypeId])
GO

ALTER TABLE [dbo].[SEntries] CHECK CONSTRAINT [FK_SEntries_ObjectTypes]
GO

ALTER TABLE [dbo].[SEntries]  WITH CHECK ADD  CONSTRAINT [FK_SEntries_SourceApps] FOREIGN KEY([SourceAppId])
REFERENCES [dbo].[SourceApps] ([SourceAppId])
GO

ALTER TABLE [dbo].[SEntries] CHECK CONSTRAINT [FK_SEntries_SourceApps]
GO

16
Bunu anlamaya çalışmak için biraz zaman harcayacak bir sonraki kişi için, kodda başka bir yerde, hiç DB'de depolanacak bir sınıf olmasa da, SEntry'den miras kalan bir sınıfım vardı. . Tek yapmam gereken bu sınıfın bir özelliği olarak [NotMapped] 'i eklemekti!
Marcelo Calbucci

Identitymodel.cs ApplicationUser sınıfına [NotMapped] koymazsanız bu hatayı alıyorum
Heemanshu Bhalla

Yanıtlar:


319

Entity Framework'ün, türetilmiş sınıf DB'ye kaydedilmese bile, veritabanındaki bir tabloya eşlenen bir POCO sınıfından miras alan herhangi bir sınıfın bir Ayırıcı sütunu gerektirdiğini varsayacağı ortaya çıkıyor.

Çözüm oldukça basittir ve [NotMapped]türetilmiş sınıfın bir özniteliği olarak eklemeniz yeterlidir .

Misal:

class Person
{
    public string Name { get; set; }
}

[NotMapped]
class PersonViewModel : Person
{
    public bool UpdateProfile { get; set; }
}

Şimdi, Person sınıfını veritabanındaki Kişi tablosuyla eşleseniz bile, türetilmiş sınıfın bir "Diskriminator" sütunu oluşturulmaz [NotMapped] .

Ek bir ipucu [NotMapped]olarak, DB'deki bir alanla eşlemek istemediğiniz özellikleri kullanabilirsiniz .


7
tamam bu yüzden hayatımın 3 saati var; (ama aynı şekilde tyvm. Sadece net olmak için de eklemeliyim ... türetilmiş sınıflar köşede her yerde olabilir, hiçbir şekilde kullanılmamış: yeniden sebat ve EF hala denemek ve içinde ... çok kafa karıştırıcı onları çekecektir.
rism

12
[NotMapped] bulamazsanız, lütfen "Assembly Framework" den projeye "System.ComponentModel.DataAnnotations" referansını ekleyin.
XandrUu

9
System.ComponentModel.DataAnnotations.Schema kullanarak;
ygaradon

6
ama benim durumumda child sınıfını kullanarak db tablosuna sütun eklemek için bir sınıf miras aldım. Bu yüzden bu notmapped özniteliğini çalıştırabilmek için kullanamıyorum. Bu durumda benim çözümüm ne olmalı?
sohaib

4
benim durumumda eşlenmiş değil eklemek yardımcı olmadı. ben tüm viewmodels
notmapped

44

İşte Fluent API sözdizimi.

http://blogs.msdn.com/b/adonet/archive/2010/12/06/ef-feature-ctp5-fluent-api-samples.aspx

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName { 
        get {
            return this.FirstName + " " + this.LastName;
        }
    }
}

class PersonViewModel : Person
{
    public bool UpdateProfile { get; set; }
}


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // ignore a type that is not mapped to a database table
    modelBuilder.Ignore<PersonViewModel>();

    // ignore a property that is not mapped to a database column
    modelBuilder.Entity<Person>()
        .Ignore(p => p.FullName);

}

Sadece özelliği eklemek daha iyi olmaz mıydı [NotMapped]?
Keith

1
@ Cevabım, [NotMapped] gibi öznitelikleri kullanmayan Akıcı API'yi kullanarak bir sütunun nasıl göz ardı edileceği
Walter Stabosz

1
Keith, bence tercih edilen cevap, çünkü şimdi kod ilk standardına doğru ilerliyoruz ve Walter'ın cevabı bu senaryo için daha uygun, özellikle de db geçişlerini kullanıyorsanız.
Tahir Khalid

Eğer karşıt probleminiz varsa (yani ve POCO sınıfından miras alan EF bağlı sınıf), veri modelini EF ile kirletmeden çalışabilmemin tek yolu buydu.
Paul Michaels

8

Ben sadece bu karşılaştım ve benim sorun hem System.ComponentModel.DataAnnotations.Schema.TableAttributeaynı tabloya atıfta ile iki varlık olması nedeniyle oldu .

Örneğin:

[Table("foo")]
public class foo
{
    // some stuff here
}

[Table("foo")]
public class fooExtended
{
    // more stuff here
}

ikinci bir değiştirme fooiçin foo_extendedbenim için sabit ve şimdi Masa Başı Tipi (TPT) kullanıyorum


Bu benim için işe yaramadı:The entity types 'AtencionMedica' and 'AtencionMedicaAP' cannot share table 'AtencionMedicas' because they are not in the same type hierarchy
James Reategui

Teşekkürler, bana yardımcı oldu, akıcı API kullanarak aynı sorunu vardı: var entity = modelBuilder.Entity<EntityObject>().ToTable("ENTITY_TABLE")ve sonra aynı EntityObjectya da aynı kullanan başka bir satır ENTITY_TABLE.
Mathijs Flietstra

4

Bunun gerçekleştiği başka bir senaryo, bir temel sınıf ve bir veya daha fazla alt sınıfınız olduğunda, alt sınıflardan en az birinin ek özellikler sağlamasıdır:

class Folder {
  [key]
  public string Id { get; set; }

  public string Name { get; set; }
}

// Adds no props, but comes from a different view in the db to Folder:
class SomeKindOfFolder: Folder {
}

// Adds some props, but comes from a different view in the db to Folder:
class AnotherKindOfFolder: Folder {
  public string FolderAttributes { get; set; }
}

Bunlar DbContextaşağıdaki gibi eşlenirse , Foldertaban türüne dayalı herhangi bir türe erişildiğinde "'Geçersiz sütun adı' Diskriminator '" hatası oluşur :

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<Folder>().ToTable("All_Folders");
  modelBuilder.Entity<SomeKindOfFolder>().ToTable("Some_Kind_Of_Folders");
  modelBuilder.Entity<AnotherKindOfFolder>().ToTable("Another_Kind_Of_Folders");
}

Sorunu düzeltmek için, Folderbir temel sınıfın (eşleştirilmemiş olan OnModelCreating()) aksesuarlarını bu OnModelCreatingşekilde değiştirdik - değişmeden olması gerektiğini buldum:

class FolderBase {
  [key]
  public string Id { get; set; }

  public string Name { get; set; }
}

class Folder: FolderBase {
}

class SomeKindOfFolder: FolderBase {
}

class AnotherKindOfFolder: FolderBase {
  public string FolderAttributes { get; set; }
}

Bu sorunu ortadan kaldırır, ama nedenini bilmiyorum!


teşekkürler, meataxe - bu bana bir iki saat mal oldu, ama en kötü yanı, daha önce bu problemi yaşamış olmalıydım, çünkü temel sınıfların hepsini kurmuştum. Bana bir yıl sonra "Hey, bu temel sınıf hiçbir şey yapmıyor gibi görünüyor. Sanırım sadece kaldıracağım ..." diyor ve hayatımın bir saatini asla geri dönemeyeceğim. BU NEDEN GEREKLİDİR? Keşke EF'i daha iyi anlamış olsaydım.
Wellspring

2

Başka bir durumda hatayı alıyorum ve sorun ve çözüm burada:

LevledItem adlı aynı temel sınıftan türetilmiş 2 sınıf var:

public partial class Team : LeveledItem
{
   //Everything is ok here!
}
public partial class Story : LeveledItem
{
   //Everything is ok here!
}

Ama onların DbContext, bazı kod kopyaladı ama sınıf adından birini değiştirmeyi unutma:

public class MFCTeamDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Other codes here
        modelBuilder.Entity<LeveledItem>()
            .Map<Team>(m => m.Requires("Type").HasValue(ItemType.Team));
    }

public class ProductBacklogDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Other codes here
        modelBuilder.Entity<LeveledItem>()
            .Map<Team>(m => m.Requires("Type").HasValue(ItemType.Story));
    }

Evet, ikinci Harita <Takım> Harita <Hikaye> olmalıdır. Ve bunu anlamanın yarım günü bana mal oldu!


2

Benzer bir sorunum vardı, tam olarak aynı koşullar değil ve sonra bu yazıyı gördüm . Umarım birine yardımcı olur. Görünüşe göre benim EF varlık modellerinden birini benim dbcontext db set olarak belirtilmeyen bir tür için bir temel sınıf kullanıyordu. Bu sorunu gidermek için iki tür için ortak tüm özelliklere sahip bir temel sınıf oluşturmak ve iki tür arasında yeni temel sınıftan miras gerekiyordu.

Misal:

//Bad Flow
    //class defined in dbcontext as a dbset
    public class Customer{ 
       public int Id {get; set;}
       public string Name {get; set;}
    }

    //class not defined in dbcontext as a dbset
    public class DuplicateCustomer:Customer{ 
       public object DuplicateId {get; set;}
    }


    //Good/Correct flow*
    //Common base class
    public class CustomerBase{ 
       public int Id {get; set;}
       public string Name {get; set;}
    }

    //entity model referenced in dbcontext as a dbset
    public class Customer: CustomerBase{

    }

    //entity model not referenced in dbcontext as a dbset
    public class DuplicateCustomer:CustomerBase{

       public object DuplicateId {get; set;}

    }

1

bu hata benimle oldu çünkü aşağıdakileri yaptım

  1. Veritabanındaki tablonun Sütun adını değiştirdim
  2. ( Update Model from databaseEdmx'te kullanmadım) Veritabanı şemasındaki değişiklikle eşleşmesi için özellik adını manuel olarak yeniden adlandırdım
  3. Edmx veritabanı şeması ve modelleri ile aynı olması için sınıftaki özellik adını değiştirmek için bazı refactoring yaptım

Tüm bunlara rağmen bu hatayı aldım

yani what to do

  1. Modeli Edmx'ten sildim
  2. Sağ Tıklayın ve Update Model from database

Bu modeli ve varlık çerçevesini yeniden oluşturulur will değil give you this error

umarım bu sana yardım eder


1

Eski Q, ancak gelecek nesiller için ... kendinden referanslı bir gezinme özelliğiniz ("Üst" veya "Aynı türden" Çocuklar ") da varsa aynıdır (Id Core adı) EF bekliyor. Yani, benim sınıfta "Id" özelliği WorkflowBasevardı ve aynı zamanda tür ilgili çocuk adımları bir dizi vardı WorkflowBaseve onları olmayan bir "WorkflowBaseId" (adı i varsayalım, doğal / geleneksel bir varsayılan olarak). Ben açıkça kullanılarak yapılandırmak zorunda HasMany(), WithOne()ve HasConstraintName()nasıl çapraz bunu söylemek için. Ama birkaç saatini problemin 'yerel olarak' nesnenin birincil anahtarını eşlemede olduğunu düşündüm, bu da bir dizi farklı yolu düzeltmeye çalıştım, ancak muhtemelen her zaman çalışıyordu.

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.