Kerangka Kerja Entitas - Nama Kolom Tidak Valid '* _ID "

101

Saya telah mempersempit ini menjadi beberapa masalah antara Code First dan Database first EF, tapi saya tidak yakin bagaimana cara memperbaikinya. Saya akan mencoba sejelas mungkin, tetapi sejujurnya saya sendiri kehilangan beberapa pemahaman di sini. Ini adalah Entity Framework 4.4

Saya mewarisi sebuah proyek di mana Entity Framework digunakan, tetapi banyak dari file sebenarnya telah dihapus tanpa cara nyata untuk kembali. Saya menambahkan kembali EF (Database terlebih dahulu) dan mereplikasi pengaturan T4 di mana proyek tersebut dibuat. Ini menghasilkan versi kode dari semua model database dan file kode DBContext.

Jika string koneksi saya terlihat seperti string koneksi .NET "normal", saya mendapatkan kesalahan tentang kolom yang tidak valid Nama "ProcessState_ID" tidak ada. ProcessState_ID sama sekali tidak ada di basis kode, tidak ada di file EDMX atau apa pun. Ini tampaknya merupakan beberapa konversi EF otomatis dalam kueri.

Ketika saya membuat string koneksi cocok dengan model Entity Framework, itu berfungsi dengan baik.

Sekarang dalam mencoba untuk mencocokkan kode sebelumnya dengan Entity Framework, saya ingin mempertahankan string koneksi .NET "normal".

Jadi saya punya dua pertanyaan di sini: 1. Apa cara yang baik untuk beralih dari string koneksi normal ke string koneksi EF dalam kode? 2. Apakah ada perbaikan lain di sini yang tidak saya lihat untuk menghentikan kesalahan nama kolom yang tidak valid?

Clarence Klopfstein
sumber
3
Ini juga terjadi jika Anda memiliki properti navigasi dengan hanya mendapatkan aksesor:public virtual Person Person { get; }
Şafak Gür
Tolong tandai sebuah jawaban
Prisoner ZERO

Jawaban:

90

Periksa untuk melihat apakah Anda memiliki ICollections.

Apa yang saya temukan adalah ketika Anda memiliki ICollection yang mereferensikan tabel dan tidak ada kolom yang dapat dipecahkan, itu membuat satu untuk Anda coba membuat koneksi antar tabel. Ini secara khusus terjadi dengan ICollection dan telah membuat saya "gila" mencoba mencari tahu.

drewid
sumber
43
Hanya untuk memperjelas jawaban ini, karena itu paling akurat untuk situasi saya (tetapi saya tidak mengetahuinya sampai setelah saya menemukan masalah saya). Jika Anda memiliki beberapa kesalahan terkait dengan OtherTable_ID saat Anda mengambil Tabel, buka model OtherTable Anda dan pastikan Anda tidak memiliki ICollection <Table> di sana. Tanpa hubungan yang ditentukan, framework akan secara otomatis menganggap bahwa Anda harus memiliki FK ke OtherTable dan membuat properti tambahan ini di SQL yang dihasilkan.
LUKE
15
EF menyia-nyiakan 4 jam saya
Nitin S
2
@NitinSawant Itu saja? EF menyia-nyiakan saya 4 jam sehari dengan semua duplikasi dan catatan yang tidak dilampirkan.
Jacob
@LUKE Komentar Anda menyelamatkan saya. Aku sangat mencintaimu :)
Amir Hossein Ahmadi
1
@LUKE pahlawan EF yang kita butuhkan, bukan pahlawan EF yang pantas kita dapatkan. Aku cinta kamu.
Matthew Young
63

Ini adalah entri yang terlambat bagi mereka (seperti saya) yang tidak segera memahami 2 jawaban lainnya.

Begitu...

EF mencoba memetakan ke nama YANG DIHARAPKAN dari PARENT TABLES KEY-REFERENCE ... dan sejak ... nama FOREIGN KEY "diubah atau disingkat" dalam database relasi CHILD TABLE ... Anda akan mendapatkan pesan di atas.

(perbaikan ini mungkin berbeda di antara versi EF)

FOR ME THE FIX ADALAH:
MENAMBAHKAN atribut "ForeignKey" ke model

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; }
}
Tahanan ZERO
sumber
4
Ini berhasil untuk saya. 1 sebagai satu-satunya tempat saya menemukan jawaban ini.
Jerry Benson-Montgomery
@ Jerry Saya telah menentukan kunci forign. Tapi tetap mencari file Category_Id. Anda telah menyebutkan tentang perbaikan untuk versi EF yang berbeda, bukan? Saya menggunakan EF 6.0 Apa perbaikan yang dapat saya lakukan?
Ajay Aradhya
@ ajay-aradhya Sebenarnya, orang yang awalnya menanggapi, narapidana-nol, yang berkomentar tentang versi EF yang berbeda.
Jerry Benson-Montgomery
@ JerryBenson-Montgomery tidak pernah! saya membuatnya bekerja. Itu adalah pemetaan 'satu lawan satu' yang menyebabkannya mencari *_ID. Termasuk referensi belakang bekerja dengan baik.
Ajay Aradhya
1
Anda juga dapat memperbaikinya dengan menambahkan kelas sebagian metadata sehingga Anda tidak perlu memperbaikinya saat membuat ulang. [MetadataType(typeof(MetaData))] public partial class Tour { public class MetaData { [ForeignKey(nameof(TourCategory))] public virtual TourCategory TourCategory { get; set; } } }
Carter Medlin
40

Astaga - setelah berjam-jam mencoba, akhirnya saya menemukan jawabannya.

Saya melakukan database EF6 terlebih dahulu dan saya bertanya-tanya tentang kesalahan "luas kolom tidak diketahui" - itu menghasilkan nama tabel garis bawah nama kolom untuk beberapa alasan, dan mencoba untuk menemukan kolom yang tidak ada.

Dalam kasus saya, salah satu tabel saya memiliki dua referensi kunci asing ke kunci utama yang sama di tabel lain - seperti ini:

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

EF telah menghasilkan beberapa nama kolom aneh seperti Owners_AnimalID1dan Owners_AnimalID2kemudian melanjutkan untuk memecahkan sendiri.

Triknya di sini adalah bahwa kunci asing yang membingungkan ini perlu didaftarkan ke EF menggunakan Fluent API!

Dalam konteks database utama Anda, OnModelCreatingganti metode dan ubah konfigurasi entitas. Lebih disukai, Anda akan memiliki file terpisah yang memperluas EntityConfigurationkelas, tetapi Anda dapat melakukannya secara inline.

Dengan cara apa pun Anda melakukannya, Anda perlu menambahkan sesuatu seperti ini:

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

Dan dengan itu, EF akan (mungkin) mulai bekerja seperti yang Anda harapkan. Ledakan.

Juga, Anda akan mendapatkan kesalahan yang sama jika Anda menggunakan yang di atas dengan kolom nullable - cukup gunakan .HasOptional()sebagai ganti .HasRequired().


Inilah tautan yang membuat saya melewati punuk:

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

Dan kemudian, dokumen Fluent API membantu, terutama contoh kunci asing:

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

Anda juga dapat meletakkan konfigurasi di ujung lain kunci, seperti yang dijelaskan di sini:

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

Ada beberapa masalah baru yang saya hadapi sekarang, tetapi itu adalah kesenjangan konseptual besar yang hilang. Semoga membantu!

Ben
sumber
1
Terima kasih banyak .. Saya memiliki masalah yang sama.
Sachin Parashar
Ini bekerja untuk saya juga, menambahkan baris kode serupa di file Peta: builder.HasOne(item => item.LogicalShipment).WithMany(s => s.Items).HasForeignKey(item => item.LogicalShipmentId).IsRequired();
DaminiVyas
14

Asumsi:

  • Table
  • OtherTable
  • OtherTable_ID

Sekarang pilih salah satu cara ini:


SEBUAH)

Menghapus ICollection<Table>

Jika Anda memiliki beberapa kesalahan terkait OtherTable_IDsaat Anda mengambil Table, buka OtherTablemodel Anda dan pastikan Anda tidak memilikinya ICollection<Table>di sana. Tanpa hubungan yang ditentukan, framework akan secara otomatis menganggap bahwa Anda harus memiliki FK ke OtherTable dan membuat properti tambahan ini di SQL yang dihasilkan.

Semua Kredit dari jawaban ini adalah milik @LUKE. Jawaban di atas adalah komentarnya di bawah jawaban @drewid. Saya pikir komentarnya sangat bersih sehingga saya menulis ulang sebagai jawaban.


B)

  • Tambahkan OtherTableIdkeTable

dan

  • Tentukan OtherTableIddi Tabledatabase
RAM
sumber
1
Jawaban yang sangat cemerlang!
Amir Hossein Ahmadi
Jawaban ini memang bisa dihemat dengan cepat. dan terima kasih kepada LUKE, saya membaca komentarnya. Meskipun @drewid berhasil menjadi yang terakhir dari rantai jawaban, tetapi itu luar biasa dan apa yang dibutuhkan untuk sebagian besar menghadapi situasi ini.
Div Tiwari
3

Dalam kasus saya, saya salah mendefinisikan kunci utama yang terdiri dari dua kunci asing seperti ini:

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

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

Kesalahan yang saya dapatkan adalah, "nama kolom Bar_ID tidak valid".

Menentukan kunci utama komposit dengan benar memperbaiki masalah:

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

...
Seth
sumber
3

Bagi saya penyebab perilaku ini adalah karena masalah dengan pemetaan yang ditentukan dengan Fluent API. Saya memiliki 2 tipe terkait, di mana tipe A memiliki objek tipe B opsional, dan tipe B memiliki banyak objek A.

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

Saya telah mendefinisikan pemetaan dengan api yang lancar seperti ini:

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

Tapi masalahnya, tipe B itu punya properti navigasi List<A>, jadi saya punyaSQLException Invalid column name A_Id

Saya memasang Visual Studio Debug ke EF DatabaseContext.Database.Log ke output SQL yang dihasilkan ke jendela VS Output-> Debug

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

Dan SQL yang dihasilkan memiliki 2 relasi dari B tabel -> satu dengan id yang benar dan yang lainnya dengan A_Id

Masalah untuk masalah tersebut adalah, bahwa saya tidak menambahkan B.List<A>properti navigasi ini ke dalam pemetaan.

Jadi, dalam kasus saya, pemetaan yang benar haruslah:

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

Dalam kasus saya, penyebab masalah ini adalah kendala FOREIGN KEY yang hilang pada database yang dimigrasi. Jadi ICollection virtual yang ada tidak berhasil dimuat.

Stefan Michev
sumber
1

Saya juga mengalami masalah ini dan sepertinya ada beberapa penyebab berbeda. Bagi saya itu memiliki properti id yang secara keliru didefinisikan sebagai int daripada long di kelas induk yang berisi objek navigasi. Field id dalam database didefinisikan sebagai bigint yang sesuai dengan long di C #. Ini tidak menyebabkan kesalahan waktu kompilasi tetapi menyebabkan kesalahan waktu proses yang sama seperti yang didapat 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
sumber
1

Bagi saya masalahnya adalah saya memiliki tabel yang dipetakan di aplikasi saya dua kali - sekali melalui Code First, sekali melalui Database First.

Menghapus salah satunya akan menyelesaikan masalah dalam kasus saya.

Renan
sumber
1

Bagi saya, itu terjadi karena masalah pluralisasi EF. Untuk tabel yang diakhiri dengan sesuatu seperti "-Status", EF menganggapnya tunggal adalah "-Statu". Mengubah entitas dan nama tabel DB menjadi "-StatusTypes" memperbaikinya.

Dengan cara ini, Anda tidak perlu mengganti nama model entitas setiap kali diperbarui.

Ray Lionfang
sumber
0

Jika Anda memiliki referensi kunci asing ke tabel yang sama lebih dari sekali, Anda dapat menggunakan InverseProperty

Sesuatu seperti ini-

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

Bagi saya (menggunakan Visual Studio 2017 dan model database-first di bawah Entity Framework 6.1.3), masalah hilang setelah memulai ulang Visual Studio and Rebuilding.

neuronz
sumber
Ini tampaknya bukan jawaban pasti untuk pertanyaan karena Anda tidak menjelaskan penyebabnya. Ini harus diletakkan sebagai komentar.
Ibo
0

Dalam kasus saya, data metode benih saya masih memanggil kolom tabel yang telah dijatuhkan dalam migrasi sebelumnya. Periksa kembali pemetaan Anda jika Anda menggunakan Automapper.

SauerTrout
sumber
0

Dalam kasus saya, saya sudah memiliki database (Database pertama). Terima kasih untuk semua komentar di sini, saya menemukan solusi saya:

Tabel harus memiliki hubungan tetapi nama kolom harus berbeda dan menambahkan atribut ForeignKey.

[ForeignKey ("PrestadorId")] AwmPrestadoresServicios Colaboradores virtual publik {get; set; }

Artinya, PRE_ID adalah PK, tetapi FK di tabel lain adalah PRESTADOR_ID, lalu berfungsi. Terima kasih untuk semua komentar di sini saya menemukan solusi saya. EF bekerja dengan cara yang misterius.

Mauricio Molina
sumber
0

Jika Anda mengalami masalah ini dengan properti navigasi di tabel yang sama, Anda harus mengubah nama properti kami.

Sebagai contoh :

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

Anda harus berubah AncestorIduntuk PersonId.

Tampaknya EF mencoba membuat kunci ParentIdkarena tidak dapat menemukan tabel bernama Ancestor ...

EDIT: Ini adalah perbaikan untuk Database dulu!

Pierre
sumber