Entity Framework - Недійсна назва стовпця '* _ID "


100

Я звузив це до певної проблеми між 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; }
Şafak Gür

Відповіді:


90

Перевірте, чи є у вас ICollections.

Я зрозумів, що коли у вас є ICollection, який посилається на таблицю, і немає стовпця, який він може зрозуміти, це створює для вас спробу встановити зв’язок між таблицями. Це конкретно трапляється з ICollection і змусило мене "бити", намагаючись це зрозуміти.


43
Щоб бути чітким щодо цієї відповіді, оскільки вона була найбільш точною до моєї ситуації (але я не знала її, поки не зрозуміла свою проблему). Якщо під час отримання таблиці у вас є помилка, пов’язана з OtherTable_ID, перейдіть до моделі OtherTable і переконайтеся, що у вас там немає таблиці ICollection <Table>. Якщо не визначено взаємозв'язок, фреймворк автоматично припустить, що ви повинні мати FK до OtherTable і створити ці додаткові властивості в згенерованому SQL.
LUKE

15
EF витратив свої 4 години
Нітін Савант

2
@NitinSawant Це все? EF витрачає мене 4 години на день з усіма тиражами та незакріпленими записами.
Яків

@LUKE Ваш коментар мене врятував. Я так тебе люблю :)
Амір Хоссейн Ахмаді

1
@LUKE потрібний нам герой EF, а не герой EF, якого ми заслуговуємо. Я тебе люблю.
Matthew Young

63

Це пізній запис для тих (як я), які не відразу зрозуміли інші 2 відповіді.

Так...

EF намагається зіставити ОЧИКУВАНЕ ім'я з КЛЮЧОВОЇ ДОСИЛКИ БАТЬКІВ ТАБЛИЦІ ... і оскільки ... ІНСТРУКЦІЙНИЙ КЛЮЧ був "змінений або скорочений" у зв'язку баз даних ДИТИНА ТАБЛИЦЯ ... Ви отримаєте повідомлення вище.

(це виправлення може відрізнятися в різних версіях 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 У мене визначено ключ forign. Але все-таки він шукає Category_Id. Ви вже згадували про виправлення для різних версій EF, чи не так? я використовую EF 6.0. Яке виправлення я можу виправити?
Ajay Aradhya

@ ajay-aradhya Насправді це людина, яка спочатку відповіла, в'язень-нуль, коментувала різні версії EF.
Джеррі Бенсон-Монтгомері,

@ ДжерріБенсон-Монтгомері ніколи! я змусив це працювати. Це було змушення "один до одного", що змусило його шукати *_ID. У тому числі зворотне посилання працювало нормально.
Аджай Арадхія

1
Ви також можете це виправити, додавши частковий клас метаданих, так що вам не доведеться виправляти це при регенерації. [MetadataType(typeof(MetaData))] public partial class Tour { public class MetaData { [ForeignKey(nameof(TourCategory))] public virtual TourCategory TourCategory { get; set; } } }
Картер Медлін,

39

Свята корова - після багатьох годин спроб я нарешті зрозумів це.

Я спочатку роблю базу даних 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 (можливо) почне працювати так, як ви очікуєте. Бум.

Крім того, ви отримаєте ту саму помилку, якщо ви використовуєте вищезазначене зі стовпчиком, який може обнулятися - просто використовуйте .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

14

Припущення:

  • Table
  • OtherTable
  • OtherTable_ID

Тепер виберіть один із таких способів:


А)

Видалити ICollection<Table>

Якщо у вас є помилка, пов’язана з тим, OtherTable_IDколи ви отримуєте Tableфайл, перейдіть до своєї OtherTableмоделі та переконайтеся, що у вас ICollection<Table>там немає. Якщо не визначено взаємозв'язок, фреймворк автоматично припустить, що ви повинні мати FK до OtherTable і створити ці додаткові властивості в згенерованому SQL.

Весь кредит цієї відповіді належить @LUKE. Наведена вище відповідь - це його коментар у відповіді @drewid. Я думаю, що його коментар настільки чистий, то я переписав його як відповідь.


Б)

  • Додати OtherTableIdдоTable

і

  • Визначення OtherTableIdв Tableбазі даних в

1
Така блискуча відповідь!
Амір Хоссейн Ахмаді,

Ця відповідь справді швидко врятувала день. і завдяки 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 до EF DatabaseContext.Database.Log для виведення згенерованого SQL до VS Output-> Вікно налагодження

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". Змінивши сутність та назву таблиці БД на "-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 та відновлення.


Це не виглядає остаточною відповіддю на запитання, оскільки ви не пояснюєте причину. Це слід поставити як коментар.
Ібо

0

У моєму випадку мої дані методу насіння все ще викликали стовпець таблиці, який був скинутий під час попередньої міграції. Перевірте свої відображення, якщо ви використовуєте 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) 

Вам доведеться помінятися AncestorIdнаPersonId .

Здається, EF намагається створити ключ, ParentIdбо не зміг знайти таблицю з ім'ям Предк ...

EDIT: Це виправлення для бази даних спочатку!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.