wake-up-neo.com

EF Code First "Ungültiger Spaltenname 'Discriminator'", aber keine Vererbung

In meiner Datenbank befindet sich eine Tabelle mit dem Namen SEntries (siehe unten die Anweisung CREATE TABLE). Es hat einen Primärschlüssel, ein paar Fremdschlüssel und nichts Besonderes. Ich habe viele ähnliche Tabellen in meiner Datenbank, aber aus irgendeinem Grund endete diese Tabelle mit einer "Discriminator" -Spalte in der EF-Proxy-Klasse.

So wird die Klasse in C # deklariert:

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

Wenn ich versuche, dieser Tabelle eine neue Zeile hinzuzufügen, erhalte ich die Fehlermeldung:

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

Dieses Problem tritt nur auf, wenn Sie Ihre C # -Klasse von einer anderen Klasse erben, SEntry jedoch von nichts erbt (wie Sie oben sehen können).

Wenn ich den Tooltip für den Debugger erhalte, sobald ich mit der Maus über die EMData-Instanz für die SEntries-Eigenschaft fahre, wird Folgendes angezeigt:

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

Irgendwelche Vorschläge oder Ideen, um dieser Ausgabe auf den Grund zu gehen? Ich habe versucht, die Tabelle, den Primärschlüssel und einige andere Dinge umzubenennen, aber nichts funktioniert.

SQL-Tabelle:

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
141

Es stellt sich heraus, dass Entity Framework davon ausgeht, dass jede Klasse, die von einer POCO-Klasse erbt, die einer Tabelle in der Datenbank zugeordnet ist, eine Discriminator-Spalte benötigt, auch wenn die abgeleitete Klasse nicht in der Datenbank gespeichert wird.

Die Lösung ist recht einfach und Sie müssen nur [NotMapped] Als Attribut der abgeleiteten Klasse hinzufügen.

Beispiel:

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

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

Selbst wenn Sie die Person-Klasse der Person-Tabelle in der Datenbank zuordnen, wird jetzt keine "Discriminator" -Spalte erstellt, da die abgeleitete Klasse [NotMapped] Enthält.

Als zusätzlichen Tipp können Sie [NotMapped] Für Eigenschaften verwenden, die Sie keinem Feld in der Datenbank zuordnen möchten.

300

Hier ist die Fluent API-Syntax.

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

}
42
Walter Stabosz

Ich bin gerade darauf gestoßen und mein Problem wurde dadurch verursacht, dass zwei Entitäten mit dem System.ComponentModel.DataAnnotations.Schema.TableAttribute beziehen sich auf die gleiche Tabelle.

beispielsweise:

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

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

ändern der zweiten von foo in foo_extended habe das für mich behoben und ich verwende jetzt Table Per Type (TPT)

8
Seph

Ein anderes Szenario, in dem dies auftritt, ist, wenn Sie eine Basisklasse und eine oder mehrere Unterklassen haben, in denen mindestens eine der Unterklassen zusätzliche Eigenschaften einführt:

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

Wenn diese wie folgt in DbContext zugeordnet sind, tritt der Fehler "'Ungültiger Spaltenname' Diskriminator '" auf, wenn auf einen Typ zugegriffen wird, der auf dem Basistyp Folder basiert:

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

Um das Problem zu beheben, extrahieren wir die Requisiten von Folder in eine Basisklasse (die nicht in OnModelCreating() abgebildet ist) wie folgt: OnModelCreating sollte unverändert bleiben:

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

Dies beseitigt das Problem, aber ich weiß nicht warum!

3
meataxe

Ich erhalte den Fehler in einer anderen Situation, und hier sind das Problem und die Lösung:

Ich habe 2 Klassen, die von derselben Basisklasse namens LevledItem abgeleitet sind:

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

Aber in ihrem DbContext habe ich Code kopiert, aber vergessen, einen der Klassennamen zu ändern:

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

Ja, die zweite Map <Team> sollte Map <Story> sein. Und es hat mich einen halben Tag gekostet, es herauszufinden!

2
cheny

dieser Fehler tritt bei mir auf, weil ich Folgendes getan habe

  1. Ich habe den Spaltennamen der Tabelle in der Datenbank geändert
  2. (Ich habe Update Model from database In Edmx nicht verwendet.) Ich habe den Eigenschaftsnamen manuell umbenannt, damit er mit der Änderung im Datenbankschema übereinstimmt
  3. Ich habe einige Umgestaltungen vorgenommen, um den Namen der Eigenschaft in der Klasse so zu ändern, dass er dem Datenbankschema und den Modellen in Edmx entspricht

Trotzdem habe ich diesen Fehler bekommen

also what to do

  1. Ich habe das Modell von Edmx gelöscht
  2. Rechtsklick und Update Model from database

dadurch werden das Modell und das Entity-Framework neu generiert. willnotgive you this error

hoffe das hilft dir

1

Ich hatte ein ähnliches Problem, nicht genau die gleichen Bedingungen und dann sah ich diesen Beitrag . Hoffe es hilft jemandem. Anscheinend habe ich mit einem meiner EF-Entitätsmodelle eine Basisklasse für einen Typ verwendet, der nicht als Datenbanksatz in meinem Datenbankkontext angegeben wurde. Um dieses Problem zu beheben, musste ich eine Basisklasse erstellen, die alle Eigenschaften der beiden Typen gemeinsam hatte und von der neuen Basisklasse zwischen den beiden Typen erbte.

Beispiel:

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

Altes Q, aber für die Nachwelt ... kommt es auch vor (.NET Core 2.1), wenn Sie über eine selbstreferenzierende Navigationseigenschaft ("Parent" oder "Children" desselben Typs) verfügen, der Name der Id-Eigenschaft jedoch nicht stimmt EF erwartet. Das heißt, ich hatte eine "Id" -Eigenschaft für meine Klasse mit dem Namen WorkflowBase und sie hatte eine Reihe verwandter untergeordneter Schritte, die ebenfalls vom Typ WorkflowBase waren, und sie versuchte ständig, sie zuzuordnen mit einer nicht existierenden "WorkflowBaseId" (der Name, den ich nehme, bevorzugt als natürliche/konventionelle Standardeinstellung). Ich musste es explizit mit HasMany(), WithOne() und HasConstraintName() konfigurieren, um ihm mitzuteilen, wie er verfahren soll. Aber ich verbrachte ein paar Stunden damit, zu glauben, das Problem liege in der 'lokalen' Zuordnung des Primärschlüssels des Objekts. Ich habe versucht, eine Reihe verschiedener Methoden zu beheben, die aber wahrscheinlich immer funktionierten.

1
user2403744