Codice EF Primo "Nome colonna non valido" Discriminatore "" ma nessuna eredità


154

Ho una tabella nel mio database chiamata SEntries (vedi sotto l'istruzione CREATE TABLE). Ha una chiave primaria, un paio di chiavi esterne e niente di speciale. Ho molte tabelle nel mio database simili a quella, ma per qualche ragione, questa tabella è finita con una colonna "Discriminator" nella classe proxy EF.

Ecco come viene dichiarata la classe in C #:

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; }
            ...
    }

Quando provo ad aggiungere una nuova riga a quella tabella, ottengo l'errore:

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

Questo problema si verifica solo se stai ereditando la tua classe C # da un'altra classe, ma SEntry non eredita da nulla (come puoi vedere sopra).

Inoltre, quando ottengo il suggerimento sul debugger quando passo il mouse sull'istanza EMData per la proprietà SEntries, viene visualizzato:

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...

Qualche suggerimento o idea su dove andare in fondo a questo problema? Ho provato a rinominare la tabella, la chiave primaria e alcune altre cose, ma nulla funziona.

SQL-Table:

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
Per la prossima persona che passerà un po 'di tempo a cercare di capirlo, quello che è successo è che in un altro posto nel codice, avevo una classe ereditata da SEntry, anche se non è una classe che verrà mai archiviata nel DB . Quindi tutto quello che dovevo fare era aggiungere [NotMapped] come attributo di quella classe!
Marcelo Calbucci,

Ricevo questo errore se non inserisco [NotMapped] nella classe ApplicationUser in Identitymodel.cs
Heemanshu Bhalla,

Risposte:


319

Si scopre che Entity Framework supporrà che qualsiasi classe che eredita da una classe POCO mappata a una tabella nel database richieda una colonna Discriminator, anche se la classe derivata non verrà salvata nel DB.

La soluzione è abbastanza semplice e devi solo aggiungere [NotMapped]come attributo della classe derivata.

Esempio:

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

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

Ora, anche se si mappa la classe Person sulla tabella Person sul database, non verrà creata una colonna "Discriminator" perché la classe derivata ha [NotMapped].

Come ulteriore suggerimento, è possibile utilizzare le [NotMapped]proprietà che non si desidera mappare su un campo nel DB.


7
ok, quindi passano 3 ore della mia vita; (ma tyvm lo stesso. Dovrei anche aggiungere solo per essere chiari ... le classi derivate possono essere completamente nell'angolo non utilizzate in alcun modo re: persistenza ed EF proverò comunque ad attirarli ... molto confusi.
rism

12
Se non trovi [NotMapped] aggiungi un riferimento a "System.ComponentModel.DataAnnotations" al progetto da "Assembly Framework".
XandrUu,

9
using System.ComponentModel.DataAnnotations.Schema;
Ygaradon,

6
ma nel mio caso ho ereditato una classe per aggiungere una colonna nella tabella db usando la classe child. Quindi non posso usare questo attributo non mappato per farlo funzionare. Quale dovrebbe essere la mia soluzione in questo caso?
Sohaib è uscito il

4
nel mio caso l'aggiunta non mappata non ha aiutato. non ho mappato tutti i
modelli di vista

44

Ecco la sintassi dell'API fluente.

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

}

Non sarebbe meglio solo aggiungere l' [NotMapped]attributo?
Keith,

1
@Keith la mia risposta è come ignorare una colonna usando l'API Fluent, che non usa attributi come [NotMapped]
Walter Stabosz

1
Keith questa è la risposta preferita che penso perché ora si sta muovendo verso uno standard in codice e la risposta di Walter è più adatta a questo scenario, specialmente se finisci per usare le migrazioni db.
Tahir Khalid,

Laddove si riscontra il problema opposto (ovvero la classe associata a EF che eredita da una classe POCO), questo è stato l'unico modo in cui ho potuto farlo funzionare senza inquinare il modello di dati con EF.
Paul Michaels,

8

Ho appena riscontrato questo e il mio problema è stato causato dall'avere due entità entrambe con System.ComponentModel.DataAnnotations.Schema.TableAttributeriferimento alla stessa tabella.

per esempio:

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

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

cambiando il secondo da fooa foo_extendedrisolto questo problema per me e ora sto usando la tabella per tipo (TPT)


Questo non ha funzionato per me:The entity types 'AtencionMedica' and 'AtencionMedicaAP' cannot share table 'AtencionMedicas' because they are not in the same type hierarchy
James Reategui,

Grazie, mi ha aiutato, ho avuto lo stesso problema usando l'API fluente:, var entity = modelBuilder.Entity<EntityObject>().ToTable("ENTITY_TABLE")e poi un'altra linea usando lo stesso EntityObjecto lo stesso ENTITY_TABLE.
Mathijs Flietstra,

4

Un altro scenario in cui ciò si verifica è quando si dispone di una classe di base e una o più sottoclassi, in cui almeno una delle sottoclassi introduce proprietà aggiuntive:

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

Se questi sono mappati nel DbContextmodo seguente, si verifica l'errore "'Nome colonna non valido' Discriminatore '" quando Foldersi accede a qualsiasi tipo basato sul tipo di base:

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

Ho scoperto che per risolvere il problema, estraiamo i puntelli di Folderuna classe base (che non è mappata OnModelCreating()) in questo modo - OnModelCreatingdovrebbe essere invariato:

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

Questo elimina il problema, ma non so perché!


grazie, meataxe - mi è costato un'ora o due, ma la parte peggiore era che dovevo aver avuto questo problema prima, perché avevo impostato tutte le classi base. Un anno più tardi mi dice: "Ehi, sembra che questa classe di base non stia facendo nulla. Penso che la rimuoverò semplicemente ..." E ci sono voluti un'ora della mia vita che non tornerò mai più. PERCHÉ È RICHIESTO QUESTO? Vorrei capire meglio EF.
Fonte

2

Ottengo l'errore in un'altra situazione, e qui ci sono il problema e la soluzione:

Ho 2 classi derivate da una stessa classe base denominata LevledItem:

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

Ma nel loro DbContext, ho copiato un po 'di codice ma ho dimenticato di cambiare uno del nome della classe:

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

Sì, la seconda mappa <Squadra> dovrebbe essere Mappa <Storia>. E mi è costata mezza giornata per capirlo!


2

Ho avuto un problema simile, non esattamente le stesse condizioni e poi ho visto questo post . Spero che aiuti qualcuno. Apparentemente stavo usando uno dei miei modelli di entità EF una classe base per un tipo che non è stato specificato come un set db nel mio dbcontext. Per risolvere questo problema ho dovuto creare una classe base che avesse tutte le proprietà comuni ai due tipi ed ereditasse dalla nuova classe base tra i due tipi.

Esempio:

//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

questo errore si verifica con me perché ho fatto quanto segue

  1. Ho cambiato il nome della colonna della tabella nel database
  2. (Non l'ho usato Update Model from database in Edmx) I Rinominato manualmente Nome proprietà in modo che corrisponda alla modifica nello schema del database
  3. Ho fatto un po 'di refactoring per cambiare il nome della proprietà nella classe in modo che corrispondesse allo schema del database e ai modelli in Edmx

Nonostante tutto ciò, ho riscontrato questo errore

così what to do

  1. Ho eliminato il modello da Edmx
  2. Fare clic con il tasto destro e Update Model from database

questo rigenera il modello e non il framework delle entitàwill give you this error

spero che questo ti aiuti


1

Vecchia Q, ma per i posteri ... succede anche (.NET Core 2.1) se hai una proprietà di navigazione autoreferenziale ("Parent" o "Children" dello stesso tipo) ma il nome della proprietà Id non è quello che EF si aspetta. Cioè, avevo una proprietà "Id" nella mia classe chiamata WorkflowBasee aveva una serie di passaggi figlio correlati, anch'essi di tipo WorkflowBase, e continuava a provare ad associarli a un "WorkflowBaseId" inesistente (il nome i supponiamo che preferisca un default naturale / convenzionale). Ho dovuto configurare in modo esplicito utilizzando HasMany(), WithOne()e HasConstraintName()per dire che come per attraversare. Ma ho trascorso alcune ore a pensare che il problema fosse nella mappatura "locale" della chiave primaria dell'oggetto, che ho tentato di risolvere in diversi modi ma che probabilmente funzionava sempre.

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.