Entity Framework - ชื่อคอลัมน์ไม่ถูกต้อง '* _ID "


104

ฉันได้ จำกัด สิ่งนี้ให้แคบลงในบางปัญหาระหว่าง Code First และ Database first EF แต่ฉันไม่แน่ใจว่าจะแก้ไขอย่างไร ฉันจะพยายามทำให้ชัดเจนที่สุดเท่าที่จะทำได้ แต่จริงๆแล้วฉันพลาดความเข้าใจตรงนี้ไปบ้าง นี่คือ Entity Framework 4.4

ฉันรับช่วงโปรเจ็กต์ที่ใช้ Entity Framework แต่ไฟล์จริงหลายไฟล์ถูกลบโดยไม่มีทางย้อนกลับได้จริง ฉันเพิ่ม EF (ฐานข้อมูลก่อน) อีกครั้งและจำลองการตั้งค่า T4 ที่โครงการสร้างขึ้น สร้างโค้ดเวอร์ชันของโมเดลฐานข้อมูลทั้งหมดและไฟล์โค้ด DBContext

หากสายอักขระการเชื่อมต่อของฉันดูเหมือนสตริงการเชื่อมต่อ. NET "ปกติ" ฉันได้รับข้อผิดพลาดเกี่ยวกับคอลัมน์ที่ไม่ถูกต้องชื่อ "ProcessState_ID" ไม่มีอยู่ ProcessState_ID ไม่ได้อยู่ในโค้ดเบสเลยมันไม่ได้อยู่ในไฟล์ EDMX หรืออะไรก็ตาม ดูเหมือนจะเป็นการแปลง EF อัตโนมัติบางส่วนในข้อความค้นหา

เมื่อฉันสร้างสตริงการเชื่อมต่อให้ตรงกับโมเดล Entity Framework มันก็ใช้ได้ดี

ตอนนี้ในการพยายามจับคู่รหัสก่อนหน้ากับ Entity Framework ฉันต้องการให้สตริงการเชื่อมต่อ. NET "ปกติ"

ดังนั้นฉันมีคำถามสองข้อที่นี่: 1. วิธีที่ดีในการเปลี่ยนจากสตริงการเชื่อมต่อปกติไปเป็นสตริงการเชื่อมต่อ EF ในรหัสคืออะไร? 2. มีการแก้ไขอื่นหรือไม่ที่ฉันไม่เห็นว่าจะหยุดข้อผิดพลาดชื่อคอลัมน์ที่ไม่ถูกต้อง


3
สิ่งนี้จะเกิดขึ้นหากคุณมีคุณสมบัติการนำทางที่มีเพียงผู้เข้าถึง:public virtual Person Person { get; }
ŞafakGür

โปรดทำเครื่องหมายคำตอบ
Prisoner ZERO

คำตอบ:


96

ตรวจสอบดูว่าคุณมี ICollections หรือไม่

สิ่งที่ฉันคิดได้คือเมื่อคุณมี ICollection ที่อ้างอิงตารางและไม่มีคอลัมน์ที่สามารถคิดออกได้มันจะสร้างขึ้นมาเพื่อให้คุณพยายามเชื่อมต่อระหว่างตาราง สิ่งนี้เกิดขึ้นโดยเฉพาะกับ ICollection และทำให้ฉัน "บ้าคลั่ง" พยายามคิดออก


46
เพื่อให้ชัดเจนกับคำตอบนี้เพราะมันถูกต้องที่สุดสำหรับสถานการณ์ของฉัน (แต่ฉันไม่รู้จนกว่าฉันจะพบปัญหาของฉัน) หากคุณมีข้อผิดพลาดบางอย่างเกี่ยวกับ OtherTable_ID เมื่อคุณกำลังเรียกข้อมูลตารางไปที่โมเดล OtherTable ของคุณและตรวจสอบให้แน่ใจว่าคุณไม่มี ICollection <Table> อยู่ในนั้น หากไม่มีการกำหนดความสัมพันธ์เฟรมเวิร์กจะสมมติโดยอัตโนมัติว่าคุณต้องมี FK ไปยัง OtherTable และสร้างคุณสมบัติพิเศษเหล่านี้ใน SQL ที่สร้างขึ้น
LUKE

15
EF เสียเวลาไป 4 ชั่วโมง
Nitin S

2
@NitinSawant นั่นเหรอ? EF ทำให้ฉันเสียเวลาวันละ 4 ชั่วโมงกับการทำซ้ำและบันทึกที่ไม่ได้แนบมาทั้งหมด
เจคอบ

@LUKE ความคิดเห็นของคุณช่วยฉันไว้ ฉันรักคุณมาก :)
อาราด

1
@LUKE ฮีโร่ EF ที่เราต้องการไม่ใช่ฮีโร่ EF ที่เราสมควรได้รับ ฉันรักคุณ.
Matthew Young

65

นี่เป็นรายการล่าช้าสำหรับผู้ที่ (เช่นฉัน) ที่ไม่เข้าใจอีก 2 คำตอบในทันที

ดังนั้น...

EF พยายามแมปกับชื่อ EXPECTED จาก PARENT TABLES KEY-REFERENCE ... และเนื่องจาก ... ชื่อ FOREIGN KEY ถูก "เปลี่ยนหรือย่อ" ในฐานข้อมูลความสัมพันธ์ CHILD TABLE ... คุณจะได้รับข้อความด้านบน

(การแก้ไขนี้อาจแตกต่างกันระหว่างเวอร์ชันของ EF)

สำหรับฉันการแก้ไขคือการ
เพิ่มแอตทริบิวต์ "ForeignKey" ให้กับโมเดล

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

4
สิ่งนี้ได้ผลสำหรับฉัน +1 เพราะเป็นที่เดียวที่ฉันพบคำตอบนี้
Jerry Benson-Montgomery

@ เจอร์รี่ฉันมีคีย์ forign กำหนดไว้ แต่ก็ยังค้นหาไฟล์Category_Id. คุณได้พูดถึงการแก้ไขสำหรับ EF เวอร์ชันต่างๆแล้วใช่หรือไม่? ฉันใช้ EF 6.0 ฉันสามารถแก้ไขอะไรได้บ้าง
Ajay Aradhya

@ ajay-aradhya อันที่จริงมันเป็นคนที่ตอบกลับมา แต่เดิมนักโทษ - ศูนย์ที่แสดงความคิดเห็นเกี่ยวกับ EF เวอร์ชันต่างๆ
Jerry Benson-Montgomery

@ JerryBenson-Montgomery ไม่เป็นไร! ฉันทำให้มันได้ผล มันเป็น '1-1' *_IDทำแผนที่ซึ่งก่อให้เกิดการค้นหา รวมถึงการอ้างอิงด้านหลังก็ใช้ได้ดี
Ajay Aradhya

1
คุณยังสามารถแก้ไขได้โดยเพิ่มคลาสบางส่วนของข้อมูลเมตาดังนั้นคุณจะไม่ต้องแก้ไขปัญหานี้เมื่อคุณสร้างใหม่ [MetadataType(typeof(MetaData))] public partial class Tour { public class MetaData { [ForeignKey(nameof(TourCategory))] public virtual TourCategory TourCategory { get; set; } } }
Carter Medlin

43

ในที่สุดฉันก็คิดออก

ฉันกำลังทำฐานข้อมูล EF6 ก่อนและฉันสงสัยเกี่ยวกับข้อผิดพลาด "คอลัมน์ที่ไม่ทราบขอบเขต" - มันกำลังสร้างชื่อตารางขีดล่างชื่อคอลัมน์ด้วยเหตุผลบางประการและพยายามค้นหาคอลัมน์ที่ไม่มีอยู่

ในกรณีของฉันหนึ่งในตารางของฉันมีการอ้างอิงคีย์ต่างประเทศสองรายการไปยังคีย์หลักเดียวกันในตารางอื่นซึ่งเป็นดังนี้:

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

EF ถูกสร้างชื่อคอลัมน์บางแปลกเหมือนOwners_AnimalID1และOwners_AnimalID2และดำเนินการที่จะทำลายตัวเองแล้ว

เคล็ดลับคือคีย์ต่างประเทศที่สับสนเหล่านี้จำเป็นต้องลงทะเบียนกับ EF โดยใช้ Fluent API!

ในบริบทฐานข้อมูลหลักของคุณให้แทนที่OnModelCreatingวิธีการและเปลี่ยนการกำหนดค่าเอนทิตี โดยเฉพาะอย่างยิ่งคุณจะมีไฟล์แยกต่างหากซึ่งจะขยายEntityConfigurationชั้นเรียน แต่คุณสามารถทำได้แบบอินไลน์

ไม่ว่าคุณจะทำอย่างไรคุณจะต้องเพิ่มสิ่งนี้:

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

และด้วยเหตุนี้ EF จะ (อาจ) เริ่มทำงานตามที่คุณคาดหวัง บูม

นอกจากนี้คุณยังจะได้รับข้อผิดพลาดเดียวกันว่าถ้าคุณใช้ข้างต้นด้วยคอลัมน์ nullable - เพียงแค่ใช้แทน.HasOptional().HasRequired()


นี่คือลิงค์ที่ทำให้ฉันอยู่เหนือโคก:

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

จากนั้นเอกสาร Fluent API จะช่วยโดยเฉพาะตัวอย่างคีย์ต่างประเทศ:

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

คุณยังสามารถวางการกำหนดค่าไว้ที่ปลายอีกด้านของคีย์ได้ตามที่อธิบายไว้ที่นี่:

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

มีปัญหาใหม่บางอย่างที่ฉันพบในตอนนี้ แต่นั่นคือช่องว่างทางความคิดขนาดใหญ่ที่ขาดหายไป หวังว่าจะช่วยได้!


1
ขอบคุณมาก .. ฉันมีปัญหาเดียวกัน
Sachin Parashar

สิ่งนี้ใช้ได้ผลสำหรับฉันเช่นกันเพิ่มบรรทัดรหัสที่คล้ายกันในไฟล์แผนที่: builder.HasOne(item => item.LogicalShipment).WithMany(s => s.Items).HasForeignKey(item => item.LogicalShipmentId).IsRequired();
DaminiVyas

15

สมมติฐาน:

  • Table
  • OtherTable
  • OtherTable_ID

ตอนนี้เลือกหนึ่งในวิธีนี้:


ก)

ลบ ICollection<Table>

หากคุณมีข้อผิดพลาดบางอย่างเกี่ยวกับOtherTable_IDเวลาที่คุณกำลังดึงข้อมูลTableให้ไปที่OtherTableโมเดลของคุณและตรวจสอบให้แน่ใจว่าคุณไม่มีICollection<Table>อยู่ในนั้น หากไม่มีการกำหนดความสัมพันธ์เฟรมเวิร์กจะสมมติโดยอัตโนมัติว่าคุณต้องมี FK ไปยัง OtherTable และสร้างคุณสมบัติพิเศษเหล่านี้ใน SQL ที่สร้างขึ้น

เครดิตทั้งหมดของคำตอบนี้เป็นของ @LUKE คำตอบข้างต้นคือความคิดเห็นของเขาภายใต้คำตอบ @drewid ฉันคิดว่าความคิดเห็นของเขาสะอาดมากแล้วฉันก็เขียนใหม่เป็นคำตอบ


B)

  • เพิ่มOtherTableIdไปที่Table

และ

  • กําหนดOtherTableIdในTableฐานข้อมูลใน

1
ช่างเป็นคำตอบที่ยอดเยี่ยม!
Arad

คำตอบนี้บันทึกไว้อย่างรวดเร็วในแต่ละวัน และขอบคุณ LUKE ที่ฉันอ่านความคิดเห็นของเขา แม้ว่า @drewid จะอยู่ในลำดับสุดท้ายของห่วงโซ่คำตอบ แต่มันยอดเยี่ยมและสิ่งที่จำเป็นสำหรับการเผชิญกับสถานการณ์นี้มากที่สุด
Div Tiwari

3

ในกรณีของฉันฉันกำหนดคีย์หลักที่ประกอบด้วยคีย์ต่างประเทศสองคีย์ไม่ถูกต้องดังนี้:

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

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

ข้อผิดพลาดที่ฉันได้รับคือ "ชื่อคอลัมน์ไม่ถูกต้อง Bar_ID"

การระบุคีย์หลักแบบผสมช่วยแก้ไขปัญหาได้อย่างถูกต้อง:

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

...

3

สำหรับฉันสาเหตุของพฤติกรรมนี้เป็นเพราะปัญหาเกี่ยวกับการแมปที่กำหนดด้วย Fluent API ฉันมี 2 ประเภทที่เกี่ยวข้องโดยที่ประเภท A มีอ็อบเจ็กต์ประเภท B ที่เป็นทางเลือกและประเภท B มีอ็อบเจ็กต์ A จำนวนมาก

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

ฉันได้กำหนดการแมปด้วย API ที่คล่องแคล่วเช่นนี้:

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

แต่ปัญหาคือประเภท B นั้นมีคุณสมบัติการนำทางList<A>ดังนั้นฉันจึงมีSQLException Invalid column name A_Id

ฉันแนบ Visual Studio Debug กับ EF DatabaseContext.Database.Log to output ที่สร้าง SQL เป็น VS Output-> Debug window

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

และสร้าง SQL มี 2 ความสัมพันธ์จากตาราง B -> หนึ่งที่มีรหัสที่ถูกต้องและอื่น ๆ ที่มี A_Id

ปัญหาของปัญหาคือฉันไม่ได้เพิ่มB.List<A>คุณสมบัติการนำทางนี้ในการแมป

ดังนั้นนี่คือวิธีการทำแผนที่ที่ถูกต้องในกรณีของฉันต้องเป็น:

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

2

ในกรณีของฉันสาเหตุของปัญหานี้คือข้อ จำกัด FOREIGN KEY ที่ขาดหายไปในฐานข้อมูลที่ย้ายข้อมูล ดังนั้นจึงไม่สามารถโหลด ICollection เสมือนที่มีอยู่ได้สำเร็จ


1

ฉันก็มีปัญหานี้เช่นกันและดูเหมือนว่ามีสาเหตุที่แตกต่างกันเล็กน้อย สำหรับฉันมันมีคุณสมบัติ id ที่กำหนดโดยไม่ถูกต้องเป็น int แทนที่จะเป็น long ในคลาสพาเรนต์ที่มีอ็อบเจ็กต์การนำทาง ฟิลด์ id ในฐานข้อมูลถูกกำหนดให้เป็น bigint ซึ่งสอดคล้องกับ long ใน C # สิ่งนี้ไม่ทำให้เกิดข้อผิดพลาดเวลาคอมไพล์ แต่ทำให้เกิดข้อผิดพลาดรันไทม์เช่นเดียวกับที่ 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;
    }
}

1

สำหรับฉันปัญหาคือฉันมีการแมปตารางในแอพของฉันสองครั้ง - หนึ่งครั้งผ่าน Code First หนึ่งครั้งผ่าน Database First

การลบอย่างใดอย่างหนึ่งช่วยแก้ปัญหาในกรณีของฉัน


1

สำหรับฉันมันเกิดขึ้นเนื่องจากปัญหาการทำให้เป็นพหูพจน์ของ EF สำหรับตารางที่ลงท้ายด้วย "-Status" EF จะคิดว่ามันเป็นเอกพจน์คือ "-Statu" การเปลี่ยนชื่อตารางเอนทิตีและ DB เป็น "-StatusTypes" ได้รับการแก้ไข

ด้วยวิธีนี้คุณไม่จำเป็นต้องเปลี่ยนชื่อโมเดลเอนทิตีทุกครั้งที่มีการอัปเดต


0

หากคุณมีการอ้างอิงคีย์ภายนอกในตารางเดียวกันมากกว่าหนึ่งครั้งคุณสามารถใช้ InverseProperty

อะไรทำนองนี้ -

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

0

สำหรับฉัน (โดยใช้ Visual Studio 2017 และโมเดลฐานข้อมูลแรกภายใต้ Entity Framework 6.1.3) ปัญหานี้หายไปหลังจากรีสตาร์ท Visual Studio และสร้างใหม่


นี่ไม่ใช่คำตอบที่ชัดเจนสำหรับคำถามเนื่องจากคุณไม่ได้อธิบายสาเหตุ ควรใส่เป็นข้อคิด
Ibo

0

ในกรณีของฉันข้อมูลวิธีการ seed ของฉันยังคงเรียกคอลัมน์ตารางซึ่งถูกทิ้งในการย้ายข้อมูลครั้งก่อน ตรวจสอบการแมปของคุณอีกครั้งหากคุณใช้ Automapper


0

ในกรณีของฉันฉันมีฐานข้อมูลอยู่แล้ว (Database firts) ขอบคุณสำหรับความคิดเห็นทั้งหมดที่นี่ฉันพบวิธีแก้ปัญหาของฉัน:

ตารางต้องมีความสัมพันธ์ แต่ชื่อของคอลัมน์ต้องแตกต่างกันและเพิ่มแอตทริบิวต์ ForeignKey

[ForeignKey ("PrestadorId")] AwmPrestadoresServicios Colaboradores เสมือนสาธารณะ {get; ชุด; }

นั่นคือ PRE_ID คือ PK แต่ FK ในอีกตารางคือ PRESTADOR_ID จึงใช้ได้ ขอบคุณสำหรับความคิดเห็นทั้งหมดที่นี่ฉันพบวิธีแก้ปัญหาของฉัน EF ทำงานในรูปแบบลึกลับ


0

หากคุณมีปัญหากับคุณสมบัติการนำทางในตารางเดียวกันคุณจะต้องเปลี่ยนชื่อคุณสมบัติของเรา

ตัวอย่างเช่น :

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

คุณจะต้องมีการเปลี่ยนแปลงสำหรับAncestorIdPersonId

ดูเหมือนว่า EF จะพยายามสร้างคีย์ParentIdเพราะไม่พบตารางชื่อ Ancestor ...

แก้ไข: นี่คือการแก้ไขสำหรับฐานข้อมูลก่อน!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.