Entity Framework - Ungültiger Spaltenname '* _ID "

99

Ich habe dies auf ein Problem zwischen Code First und Database First EF eingegrenzt, bin mir aber nicht sicher, wie ich es beheben soll. Ich werde versuchen, so klar wie möglich zu sein, aber ich vermisse hier ehrlich gesagt etwas von dem Verständnis. Dies ist Entity Framework 4.4

Ich habe ein Projekt geerbt, in dem Entity Framework verwendet wurde, aber viele der tatsächlichen Dateien wurden gelöscht, ohne dass es einen wirklichen Weg gab, zurück zu gehen. Ich habe EF (Datenbank zuerst) erneut hinzugefügt und ein T4-Setup repliziert, um das das Projekt herum erstellt wurde. Es wurden Codeversionen aller Datenbankmodelle und eine DBContext-Codedatei generiert.

Wenn meine Verbindungszeichenfolge wie eine "normale" .NET-Verbindungszeichenfolge aussieht, wird eine Fehlermeldung angezeigt, dass eine ungültige Spalte mit dem Namen "ProcessState_ID" nicht vorhanden ist. ProcessState_ID befindet sich überhaupt nicht in der Codebasis, nicht in der EDMX-Datei oder so. Dies scheint eine automatische EF-Konvertierung in der Abfrage zu sein.

Wenn ich die Verbindungszeichenfolge mit dem Entity Framework-Modell übereinstimme, funktioniert sie einwandfrei.

Beim Versuch, den vorherigen Code mit Entity Framework abzugleichen, möchte ich die "normale" .NET-Verbindungszeichenfolge beibehalten.

Ich habe hier also zwei Fragen: 1. Was ist ein guter Weg, um von einer normalen Verbindungszeichenfolge zu einer EF-Verbindungszeichenfolge im Code zu gelangen? 2. Gibt es hier einen anderen Fix, den ich nicht sehe, um den ungültigen Spaltennamenfehler zu stoppen?

Clarence Klopfstein
quelle
3
Dies passiert auch, wenn Sie eine Navigationseigenschaft mit nur einem Get Accessor haben:public virtual Person Person { get; }
Şafak Gür

Antworten:

90

Überprüfen Sie, ob Sie ICollections haben.

Was ich herausgefunden habe, ist, wenn Sie eine ICollection haben, die auf eine Tabelle verweist, und es keine Spalte gibt, die herausgefunden werden kann. Sie erstellt eine Spalte, in der Sie versuchen können, die Verbindung zwischen den Tabellen herzustellen. Dies passiert speziell bei ICollection und hat mich "verrückt" gemacht, um es herauszufinden.

zogid
quelle
43
Nur um diese Antwort klar zu machen, weil sie meiner Situation am genauesten entsprach (aber ich wusste es erst, nachdem ich mein Problem herausgefunden hatte). Wenn beim Abrufen der Tabelle ein Fehler im Zusammenhang mit OtherTable_ID auftritt, wechseln Sie zu Ihrem OtherTable-Modell und stellen Sie sicher, dass dort keine ICollection <Table> vorhanden ist. Ohne eine definierte Beziehung geht das Framework automatisch davon aus, dass Sie eine FK für OtherTable haben müssen, und erstellt diese zusätzlichen Eigenschaften in der generierten SQL.
Luke
15
EF verschwendete meine 4 Stunden
Nitin Sawant
2
@NitinSawant Das ist es? EF verschwendet mich 4 Stunden am Tag mit all seinen Duplikaten und nicht angehängten Aufzeichnungen.
Jacob
@ Luke Dein Kommentar hat mich gerettet. Ich liebe dich so sehr :)
Amir Hossein Ahmadi
1
@ Luke der EF-Held, den wir brauchen, nicht der EF-Held, den wir verdienen. Ich liebe dich.
Matthew Young
62

Dies ist ein später Eintrag für diejenigen (wie ich), die die anderen 2 Antworten nicht sofort verstanden haben.

So...

EF versucht, den Namen EXPECTED aus der KEENT-REFERENZ DER PARENT TABLES zuzuordnen ... und da ... der Name der FOREIGN KEY in der CHILD TABLE-Beziehung der Datenbank "geändert oder gekürzt" wurde, wird die obige Meldung angezeigt.

(Dieser Fix kann zwischen den Versionen von EF unterschiedlich sein.)

Für mich war
das Update : Hinzufügen des Attributs "ForeignKey" zum Modell

public partial class Tour
{
    public Guid Id { get; set; }

    public Guid CategoryId { get; set; }

    [Required]
    [StringLength(200)]
    public string Name { get; set; }

    [StringLength(500)]
    public string Description { get; set; }

    [StringLength(50)]
    public string ShortName { get; set; }

    [StringLength(500)]
    public string TourUrl { get; set; }

    [StringLength(500)]
    public string ThumbnailUrl { get; set; }

    public bool IsActive { get; set; }

    [Required]
    [StringLength(720)]
    public string UpdatedBy { get; set; }

    [ForeignKey("CategoryId")]
    public virtual TourCategory TourCategory { get; set; }
}
Gefangener NULL
quelle
4
Das hat bei mir funktioniert. +1 als einziger Ort, an dem ich diese Antwort gefunden habe.
Jerry Benson-Montgomery
@ Jerry Ich habe den Auslandsschlüssel definiert. Trotzdem sucht es nach dem Category_Id. Sie haben über die Korrekturen für verschiedene Versionen von EF gesprochen, oder? Ich verwende EF 6.0. Was ist das Update, das ich nicht anwenden kann?
Ajay Aradhya
@ ajay-aradhya Eigentlich war es die Person, die ursprünglich geantwortet hat, Gefangener-Null, die den Kommentar zu verschiedenen Versionen von EF abgegeben hat.
Jerry Benson-Montgomery
@ JerryBenson-Montgomery vergiss es! Ich habe es geschafft. Es war das Eins-zu-Eins-Mapping, nach dem gesucht wurde *_ID. Das Einbeziehen der Rückreferenz hat gut funktioniert.
Ajay Aradhya
1
Sie können dies auch beheben, indem Sie eine Metadaten-Teilklasse hinzufügen, damit Sie dies beim Regenerieren nicht beheben müssen. [MetadataType(typeof(MetaData))] public partial class Tour { public class MetaData { [ForeignKey(nameof(TourCategory))] public virtual TourCategory TourCategory { get; set; } } }
Carter Medlin
39

Heilige Kuh - nach vielen Stunden des Versuchs habe ich es endlich herausgefunden.

Ich mache zuerst eine EF6-Datenbank und habe mich über den Fehler "Umfang unbekannte Spalte" gewundert - es wurde aus irgendeinem Grund ein Tabellenname generiert, der den Spaltennamen unterstreicht, und versucht, eine nicht vorhandene Spalte zu finden.

In meinem Fall hatte eine meiner Tabellen zwei Fremdschlüsselreferenzen auf denselben Primärschlüssel in einer anderen Tabelle - ungefähr so:

Animals            Owners
=======            ======
AnimalID (PK)      Pet1ID    <- FK to AnimalID
                   Pet2ID    <- also FK to AnimalID

EF erzeugte einen seltsamen Spaltennamen wie Owners_AnimalID1und Owners_AnimalID2fuhr dann fort, sich selbst zu brechen.

Der Trick dabei ist, dass diese verwirrenden Fremdschlüssel mithilfe der Fluent API bei EF registriert werden müssen!

Überschreiben Sie in Ihrem Hauptdatenbankkontext die OnModelCreatingMethode und ändern Sie die Entitätskonfiguration. Vorzugsweise haben Sie eine separate Datei, die die EntityConfigurationKlasse erweitert, aber Sie können dies inline tun.

Wie auch immer Sie es tun, Sie müssen Folgendes hinzufügen:

public class OwnerConfiguration : EntityTypeConfiguration<Owner>
{
    public OwnerConfiguration()
    {
        HasRequired(x => x.Animals)
            .WithMany(x => x.Owners)  // Or, just .WithMany()
            .HasForeignKey(x => x.Pet1ID);
    }
}

Und damit wird EF (vielleicht) anfangen zu arbeiten, wie Sie es erwarten. Boom.

Diesen Fehler erhalten Sie auch, wenn Sie den obigen Fehler mit einer nullbaren Spalte verwenden - verwenden Sie einfach .HasOptional()anstelle von .HasRequired().


Hier ist der Link, der mich über den Berg gebracht hat:

https://social.msdn.microsoft.com/Forums/en-US/862abdae-b63f-45f5-8a6c-0bdd6eeabfdb/getting-sqlexception-invalid-column-name-userid-from-ef4-codeonly?forum=adonetefx

Und dann helfen die Fluent API-Dokumente, insbesondere die Fremdschlüsselbeispiele:

http://msdn.microsoft.com/en-us/data/jj591620.aspx

Sie können die Konfigurationen auch am anderen Ende des Schlüssels platzieren, wie hier beschrieben:

http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx .

Es gibt einige neue Probleme, auf die ich jetzt stoße, aber das war die große konzeptionelle Lücke, die fehlte. Ich hoffe es hilft!

Ben
quelle
1
Vielen Dank. Ich hatte das gleiche Problem.
Sachin Parashar
14

Annahmen:

  • Table
  • OtherTable
  • OtherTable_ID

Wählen Sie nun eine der folgenden Möglichkeiten:


EIN)

Entfernen ICollection<Table>

Wenn OtherTable_IDbeim Abrufen ein Fehler auftritt Table, gehen Sie zu Ihrem OtherTableModell und stellen Sie sicher, dass dort kein Fehler ICollection<Table>vorhanden ist. Ohne eine definierte Beziehung geht das Framework automatisch davon aus, dass Sie eine FK für OtherTable haben müssen, und erstellt diese zusätzlichen Eigenschaften in der generierten SQL.

Das gesamte Guthaben dieser Antwort gehört @LUKE. Die obige Antwort ist sein Kommentar unter @drewid Antwort. Ich denke, sein Kommentar ist so sauber, dass ich ihn als Antwort umgeschrieben habe.


B)

  • Hinzufügen OtherTableIdzuTable

und

  • Definieren Sie OtherTableIdin der Tablein der Datenbank
RAM
quelle
1
So eine brillante Antwort!
Amir Hossein Ahmadi
Diese Antwort wurde tatsächlich tagsüber schnell gespeichert. und dank LUKE habe ich seinen Kommentar gelesen. @Drewid hat es zwar am Ende der Antwortkette geschafft, aber es war hervorragend und was für die meisten benötigt wurde, die sich dieser Situation stellen mussten.
Div Tiwari
3

In meinem Fall habe ich einen Primärschlüssel, der aus zwei Fremdschlüsseln besteht, falsch definiert:

HasKey(x => x.FooId);
HasKey(x => x.BarId);

HasRequired(x => x.Foo)
    .WithMany(y => y.Foos);
HasRequired(x => x.Bar);

Der Fehler, den ich erhielt, war "ungültiger Spaltenname Bar_ID".

Durch die korrekte Angabe des zusammengesetzten Primärschlüssels wurde das Problem behoben:

HasKey(x => new { x.FooId, x.BarId });

...
Seth
quelle
3

Für mich war die Ursache für dieses Verhalten ein Problem mit der definierten Zuordnung mit der Fluent-API. Ich hatte 2 verwandte Typen, wobei Typ A ein optionales Typ B-Objekt hatte und Typ B viele A-Objekte hatte.

public class A 
{
    
    public int? BId {get; set;}
    public B NavigationToBProperty {get; set;}
}
public class B
{
    
    public List<A> ListOfAProperty {get; set;}
}

Ich hatte Mapping mit fließender API wie folgt definiert:

A.HasOptional(p=> p.NavigationToBProperty).WithMany().HasForeignKey(key => key.BId);

Aber das Problem war, dass Typ B Navigationseigenschaften hatte List<A>, also als Ergebnis hatte ichSQLException Invalid column name A_Id

Ich habe Visual Studio Debug an EF DatabaseContext.Database.Log angehängt, um generiertes SQL in das Fenster VS Output-> Debug auszugeben

db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

Und generiertes SQL hatte 2 Beziehungen aus der B-Tabelle -> eine mit der richtigen ID und eine mit der A_Id

Das Problem für das Problem war, dass ich diese B.List<A>Navigationseigenschaft nicht zum Mapping hinzugefügt habe .

So musste in meinem Fall die korrekte Zuordnung sein:

A.HasOptional(p=> p.NavigationToBProperty).WithMany(x => x.ListOfAProperty).HasForeignKey(key => key.BId);
Prokuroren
quelle
2

In meinem Fall war die Ursache für dieses Problem eine fehlende FOREIGN KEY-Einschränkung für eine migrierte Datenbank. Daher wurde die vorhandene virtuelle ICollection nicht erfolgreich geladen.

Stefan Michev
quelle
1

Ich hatte auch dieses Problem und es scheint, dass es ein paar verschiedene Ursachen gibt. Für mich war es eine id-Eigenschaft, die fälschlicherweise als int statt long in der übergeordneten Klasse definiert wurde, die ein Navigationsobjekt enthielt. Das ID-Feld in der Datenbank wurde als bigint definiert, was long in C # entspricht. Dies verursachte keinen Kompilierungsfehler, verursachte jedoch denselben Laufzeitfehler wie das OP:

// Domain model parent object
public class WidgetConfig 
{
    public WidgetConfig(long id, int stateId, long? widgetId)
    {
        Id = id;
        StateId = stateId;
        WidgetId = widgetId;
    }

    private WidgetConfig()
    {
    }

    public long Id { get; set; }

    public int StateId { get; set; }

    // Ensure this type is correct
    public long? WidgetId { get; set; } 

    public virtual Widget Widget { get; set; }
}

// Domain model object
public class Widget
{
    public Widget(long id, string name, string description)
    {
        Id = id;
        Name = name;
        Description = description;
    }

    private Widget()
    {
    }

    public long Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }
}

// EF mapping
public class WidgetConfigMap : EntityTypeConfiguration<WidgetConfig>
{
    public WidgetConfigMap()
    {
        HasKey(x => x.Id);
        ToTable(nameof(WidgetConfig));
        Property(x => x.Id).HasColumnName(nameof(WidgetConfig.Id)).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
        Property(x => x.StateId).HasColumnName(nameof(WidgetConfig.StateId));
        Property(x => x.WidgetId).HasColumnName(nameof(WidgetConfig.WidgetId));
    }
}   

// Service
public class WidgetsService : ServiceBase, IWidgetsService
{
    private IWidgetsRepository _repository;

    public WidgetsService(IWidgetsRepository repository)
    {
        _repository = repository;
    }

    public List<WidgetConfig> ListWithDetails()
    {
        var list = _repository.ListWithDetails();

        return new WidgetConfigMapping().ConvertModelListToDtoList(list).ToList();
    }
}   

// Repository
public class WidgetsRepository: BaseRepository<WidgetConfig, long>, IWidgetsRepository
{
    public WidgetsRepository(Context context)
        : base(context, id => widget => widget.Id == id)
    {
    }

    public IEnumerable<WidgetConfig> ListWithDetails()
    {
        var widgets = Query
            .Include(x => x.State)
            .Include(x => x.Widget);

        return widgets;
    }
}
Ciaran Bruen
quelle
1

Für mich besteht das Problem darin, dass ich die Tabelle zweimal in meiner App zugeordnet habe - einmal über Code First, einmal über Database First.

Das Entfernen einer der beiden Lösungen löst das Problem in meinem Fall.

Renan
quelle
1

Für mich geschah dies aufgrund der Pluralisierungsprobleme von EF. Für Tabellen, die mit so etwas wie "-Status" enden, glaubt EF, dass der Singular "-Statu" ist. Durch Ändern des Namens der Entität und der DB-Tabelle in "-StatusTypes" wurde das Problem behoben.

Auf diese Weise müssten Sie Entitätsmodelle nicht jedes Mal umbenennen, wenn sie aktualisiert werden.

Ray Lionfang
quelle
0

Wenn Sie mehrmals Fremdschlüsselverweise auf dieselbe Tabelle haben, können Sie InverseProperty verwenden

Etwas wie das-

[InverseProperty("MyID1")]
public virtual ICollection<MyTable> set1 { get; set; }
[InverseProperty("MyID2")]
public virtual ICollection<MyTable> set2 { get; set; }
Pallavi
quelle
0

Für mich (mit Visual Studio 2017 und dem Datenbank-First-Modell unter Entity Framework 6.1.3) ist das Problem nach dem Neustart von Visual Studio und der Neuerstellung behoben.

neuronz
quelle
Dies scheint keine endgültige Antwort auf die Frage zu sein, da Sie die Ursache nicht erklären. Es sollte als Kommentar gesetzt werden.
Ibo
0

In meinem Fall haben meine Seed-Methodendaten immer noch eine Tabellenspalte aufgerufen, die bei einer früheren Migration gelöscht wurde. Überprüfen Sie Ihre Zuordnungen, wenn Sie Automapper verwenden.

SauerTrout
quelle
0

In meinem Fall habe ich bereits eine Datenbank (Database Firts). Dank aller Kommentare hier habe ich meine Lösung gefunden:

Die Tabellen müssen die Beziehung haben, aber der Name der Spalten muss unterschiedlich sein und das ForeignKey-Attribut hinzufügen.

[ForeignKey ("PrestadorId")] öffentliche virtuelle AwmPrestadoresServicios Colaboradores {get; einstellen; }}

Das heißt, PRE_ID ist PK, aber FK in der anderen Tabelle ist PRESTADOR_ID, dann funktioniert es. Dank aller Kommentare hier habe ich meine Lösung gefunden. EF arbeitet auf mysteriöse Weise.

Mauricio Molina
quelle
0

Wenn Sie dieses Problem mit einer Navigationseigenschaft in derselben Tabelle haben, müssen Sie den Namen unserer Eigenschaft ändern.

Zum Beispiel :

Table : PERSON
Id
AncestorId (with a foreign key which references Id named Parent) 

Du musst dich umziehen AncestorIdfür PersonId.

Es scheint, dass EF versucht, einen Schlüssel zu erstellen, ParentIdweil es keine Tabelle mit dem Namen Ancestor finden konnte ...

EDIT: Dies ist ein Fix für die Datenbank zuerst!

Pierre
quelle