Тип сутності <type> не є частиною моделі для поточного контексту


146

Я потрапляю в Entity Framework, але я не впевнений, якщо мені не вистачає критичної точки в підході до коду.

Я використовую загальний шаблон репозиторію на основі коду з https://genericunitofworkandrepositories.codeplex.com/ і створив мої сутності.

Але коли я намагаюся отримати доступ або змінити сутність, я стикаюся з наступним:

System.InvalidOperationException: Тип об'єкта Не є частиною моделі для поточного контексту.

Це трапляється, коли я намагаюся отримати доступ до нього зі свого сховища:

public virtual void Insert(TEntity entity)
{
    ((IObjectState)entity).ObjectState = ObjectState.Added;
    _dbSet.Attach(entity); // <-- The error occurs here
    _context.SyncObjectState(entity);
}

База даних (./SQLEXPRESS) створюється просто чудово, але сутності (таблиці) просто не створюються при запуску.

Мені цікаво, чи потрібно явно встановити відображення сутностей? Чи EF не може цього зробити самостійно?

Моя організація:

public class Estate : EntityBase
{
    public int EstateId { get; set; }
    public string Name { get; set; }
} 

Мій контекст такий:

public partial class DimensionWebDbContext : DbContextBase // DbContextBase inherits DbContext
{
    public DimensionWebDbContext() :
        base("DimensionWebContext")
    {
        Database.SetInitializer<DimensionWebDbContext>(new CreateDatabaseIfNotExists<DimensionWebDbContext>());
        Configuration.ProxyCreationEnabled = false;
    }

    public new IDbSet<T> Set<T>() where T : class
    {
        return base.Set<T>();
    }

}

Чи є якась конкретна причина, чому ця помилка виникає? Я намагався ввімкнути міграцію та ввімкнути автоматичні міграції і без допомоги.

Відповіді:


142

Розмістіть це у власному DbContextкласі:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Estate>().ToTable("Estate");
}

Якщо ваші таблиці не створені під час запуску, саме тому. Вам потрібно повідомити DbContext про них в методі OnModelCreating, який замінить.

Тут ви можете або зробити власні відображення на особи, або розділити їх на окремі EntityTypeConfiguration<T>класи.


1
Дякую, Ден - це це виправляє. Тепер таблиці створені. Іншого шляху немає, EF не може цього зробити самостійно? Я не можу просто анотувати сутність за допомогою [ToTable ('Estates')] чи щось подібне?
janhartmann

3
Я думаю, що це може спрацювати без відміни, OnModelCreatingякщо ваші організації будуть у тому ж складі, що і ваш DbContext. Я ніколи не використовував анотації даних для організацій, тому не можу сказати точно. Ви завжди можете сканувати склади у ваших, OnModelCreatingщоб знайти об'єкти в інших збірках і автоматично реєструвати їх (саме це робить штатив).
danludwig

Ах, звичайно. Дякую за примітку про спосіб штатива, я зараз щось подібне зробив, і, здається, він працює чудово. (також завдяки розширенням для роздумів на веб-сайті: github.com/danludwig/Layout3/blob/master/UCosmic.Domain/Api/… ). Тепер мені просто потрібно знайти збірки посилань, а не дивитись, що це збірка GetType (). "var Assembly = Assembly.Load (" Dimension.Web.Domain ");" не дуже ;-)
janhartmann

Або, можливо, просто перемістіть нову / Mapping / папку в мій проект Impl замість мого домену.
janhartmann

@meep або danludwig. Скажіть, будь ласка, більше про штатив або поділіться посиланням.
DkAngelito

73

Мабуть, ця помилка дуже загальна, вона може мати ряд причин. У моєму випадку це було наступне: Рядок підключення (у Web.config), згенерований файлом, .edmxбув недійсним. Після майже щоденного спроби всього я змінив рядок з'єднання з рядка EF на рядок ADO.NET. Це вирішило моє питання.

Наприклад, рядок EF виглядає приблизно так:

<connectionStrings> 
  <add name="BlogContext"  
    connectionString="metadata=res://*/BloggingModel.csdl| 
                               res://*/BloggingModel.ssdl| 
                               res://*/BloggingModel.msl; 
                               provider=System.Data.SqlClient 
                               provider connection string= 
                               &quot;data source=(localdb)\v11.0; 
                               initial catalog=Blogging;
                               integrated security=True; 
                               multipleactiveresultsets=True;&quot;" 
     providerName="System.Data.EntityClient" /> 
</connectionStrings>

І рядок ADO.NET виглядає приблизно так:

<connectionStrings>
  <add name="BlogContext"  
        providerName="System.Data.SqlClient"  
        connectionString="Server=.\SQLEXPRESS;Database=Blogging;
        Integrated Security=True;"/> 
</connectionStrings>

Джерело: http://msdn.microsoft.com/nl-nl/data/jj556606.aspx


17
Моя проблема була також у рядку з'єднання. Я перейменував свою модель даних і переробив свої шаблони t4, але забув оновити метадані (.csdl, .ssdl, .msl файли) у рядку з'єднання. Ваша відповідь допомогла мені це зрозуміти, тож дякую!
Вискол

4
Якщо для автентифікації використовується модель Identity, вам потрібні 2 рядки підключення: один, "DefaultConnection", який ви можете перейменовувати чи ні, і помістити у свій загальнодоступний ApplicationDbContext (): base ("IdentityDbContext", castIfV1Schema: false) {} Саме це викликало мою помилку як ваш (у мене був рядок EF там). Другий рядок з'єднання - це той, який створений із додавання EF за допомогою майстра, і він запитує параметри рядка Connection. Я сподіваюся, що це комусь допоможе.
JustJohn

те ж саме. неймовірно розчаровує
Нік Моліно

1
Я модернізую EF 4.xдо EF 6. Мені довелося відновити рядок з'єднання, щоб додати таблицю ( DatabaseFirst). Я не помічав, що мої зв'язки в і app.configта інші web.configбули різними. Як тільки я взяв на connectionstringозброєння app.config, він почав працювати.
DHFW

16

Для мене проблема полягала в тому, що я не включав клас сутності до мого набору db всередині контексту для сутності.

public DbSet<ModelName> ModelName { get; set; }

12

Ви можете спробувати вийняти таблицю з моделі та додати її ще раз. Це можна зробити візуально, відкривши .edmx файл із Провідника рішень.

Кроки:

  1. Двічі клацніть файл .edmx із Провідника рішень
  2. Клацніть правою кнопкою миші на головці таблиці, яку потрібно видалити, і виберіть "Видалити з моделі"
  3. Тепер знову клацніть правою кнопкою миші на робочій області і виберіть "Оновити модель з бази даних".
  4. Знову додайте таблицю зі списку таблиць
  5. Очистіть і побудуйте рішення

8
У коді EF спочатку немає .edmx.
Tuukka Haapaniemi

Я дав +1, тому що він (або хтось інший із цим питанням) може
спробувати

9

Проблема може бути в рядку з'єднання. Переконайтесь, що ваш рядок з'єднання призначений для постачальника SqlClient, без елементів метаданих, пов'язаних з EntityFramework.


Це, мабуть, було очевидно для багатьох, але це закінчилося моєю проблемою (щодо змішування db-first з кодом-першим). Тепер я можу перестати крутити колеса, велике спасибі!
Bonez024

3

Я бачив цю помилку, коли існуюча таблиця в базі даних не відображається належним чином до першої моделі коду. Зокрема, я мав char (1) у таблиці бази даних та char у C #. Зміна моделі на рядок вирішила проблему.


3

Мою проблему було вирішено шляхом оновлення частини метаданих рядка з'єднання. Мабуть, це вказувало на неправильну посилання .csdl / .ssdl / .msl.


Це сталося і зі мною. Я скопіював з'єднання EF з іншого місця та не оновив ім'я моделі в метаданих.
devC

2

Ще одна річ, яку потрібно перевірити за допомогою рядка з'єднання - назва моделі. Я використовував дві моделі сутності, спочатку БД. У налаштуваннях я скопіював з'єднання сутності для одного, перейменував його та змінив частину рядка з'єднання. Те, що я не змінив, було ім'ям моделі, тому, коли модель сутності створювалася правильно, коли контекст був ініційований, EF шукав неправильну модель для сутностей.

Виглядає очевидно записаним, але чотири години я не повернуся.


2

Для мене проблема полягала в тому, що я використовував connection stringсформований ADO.NetModel (.edmx). Змінення рядка з'єднання вирішило мою проблему.


1

Це також може статися, якщо ви використовуєте збережений кеш моделі, який застарів з тих чи інших причин. Якщо ваш контекст був кешований у файлі EDMX у файловій системі (через DbConfiguration.SetModelStore), OnModelCreating ніколи не буде викликатися, оскільки буде використана кешована версія. Як результат, якщо об'єкт відсутній у вашому кешованому магазині, ви отримаєте вищевказану помилку, навіть якщо рядок з'єднання є правильним, таблиця існує в базі даних, а сутність налаштована правильно у вашому DbContext.


1

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

Я працюю з двома контекстами DB Entity Framework sysContextтаshardContext в тому ж методі.

Суб'єкт, який я змінив \ оновив, є з одного контексту, але потім я спробував зберегти його в інший контекст, як це:

invite.uid = user.uid;

sysContext.Entry(invite).State = EntityState.Modified;

sysContext.SaveChanges(); // Got the exception here

але правильна версія повинна бути такою:

invite.uid = user.uid;

shardContext.Entry(invite).State = EntityState.Modified;

shardContext.SaveChanges();

Після переходу сутності у правильний контекст ця помилка усунулася.


0

Звучить очевидно, але переконайтеся, що ви явно не ігноруєте тип:

modelBuilder.Ignore<MyType>();


0

карта сутності (навіть порожня), додана до конфігурації, призведе до того, що тип сутності буде частиною контексту. У нас була організація, яка не має відношення до інших об'єктів, яка була зафіксована порожньою картою.


0

якщо ви спочатку намагаєтеся БД, то переконайтеся, що у вашій таблиці є первинний ключ


0

Візуальна студія 2019, схоже, викликає це для мене. Я виправив це, знову створивши модель edmx у 2017 році.


0

У мене виникає така ж проблема в Entity Framewrok, і я вирішив її за кроками:

1-Відкрийте Model.edmx 2 - змініть місце таблиці (для зміни змін у файлі CS) 3 - збережіть його

Сподіваюся, допоможу вам


0

Видаліть .edmx файл і додайте його знову. Особливо, якщо ви оновили Entity Framework.


0

Я стикався з тією ж проблемою, що EntityFrameworkCore намагався оновити діапазон значень.

Такий підхід не спрацював

  _dbSet.AttachRange(entity);
  _context.Entry(entity).State = EntityState.Modified;
   await _context.SaveChangesAsync().ConfigureAwait(false);

Після додавання методу UpdateRange та видалення додавання та введення все працює

  _dbSet.UpdateRange(entity);
  await _context.SaveChangesAsync().ConfigureAwait(false);

0

Для мене це було викликано тим, що я перейменував предметний клас. Коли я повернув його назад, це було ОК.


0

Це може бути дурним, але якщо ви отримали цю помилку лише на якійсь таблиці, не забудьте очистити проект та відновлювати його (це може заощадити багато часу)


0

У мене це було

using (var context = new ATImporterContext(DBConnection))
{
    if (GetID(entity).Equals(0))
    {
        context.Set<T>().Add(entity);
    }
    else
    {
        int val = GetID(entity);
        var entry = GetEntryAsync(context, GetID(entity)).ConfigureAwait(false);
        context.Entry(entry).CurrentValues.SetValues(entity);

    }
    
    await context.SaveChangesAsync().ConfigureAwait(false);
}

Це було в методі async, але я забув очікувати перед GetEntryAsync, і тому я отримав цю саму помилку ...

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