Тип сущности <тип> не является частью модели для текущего контекста


147

Я вхожу в Entity Framework, но я не уверен, что мне не хватает критической точки в подходе, основанном на коде.

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

Но когда я пытаюсь получить доступ или изменить сущность, я сталкиваюсь со следующим:

System.InvalidOperationException: тип объекта Estate не является частью модели для текущего контекста.

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

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

}

Есть ли какая-то конкретная причина, по которой возникает эта ошибка? Я попытался включить миграцию и включить автоматическую миграцию без какой-либо помощи.

Ответы:


143

Поместите это в свой пользовательский DbContextкласс:

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

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

Здесь вы можете сделать пользовательские сопоставления для каждой сущности или разделить их на отдельные EntityTypeConfiguration<T>классы.


1
Спасибо, Дэн, это исправляет. Теперь таблицы созданы. Другого пути нет, EF не может сделать это самостоятельно? Я не могу просто аннотировать сущность с помощью [ToTable ('Estates')] или что-то в этом роде?
Январтман

3
Я думаю, что это может работать без переопределения, OnModelCreatingесли ваши сущности находятся в той же сборке, что и ваши DbContext. Я никогда не использовал аннотации данных для сущностей, поэтому не могу сказать наверняка. Вы всегда можете сканировать сборки в вашем, OnModelCreatingчтобы найти объекты в других сборках и зарегистрировать их автоматически (что делает Tripod).
Данлудвиг

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

Или, может быть, просто переместите мою новую папку / Mapping / в мой проект Impl вместо моего домена.
Январтман

@ 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», throwIfV1Schema: false) {} Вот что вызвало мою ошибку как у тебя (у меня там была строка EF). Вторая строка подключения - это та, которая создается путем добавления EF с помощью мастера и запрашивает параметры строки подключения. Я надеюсь, что это поможет кому-то.
JustJohn

тоже самое. невероятно расстраивает
Ник Молинье

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

16

Для меня проблема заключалась в том, что я не включил класс сущностей в свой набор БД в контексте структуры сущностей.

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

12

Вы можете попробовать удалить таблицу из модели и добавить ее снова. Вы можете сделать это визуально, открыв файл .edmx в обозревателе решений.

шаги:

  1. Дважды щелкните файл .edmx в обозревателе решений.
  2. Щелкните правой кнопкой мыши на заголовке стола, который хотите удалить, и выберите «Удалить из модели».
  3. Теперь снова щелкните правой кнопкой мыши на рабочей области и выберите «Обновить модель из базы данных».
  4. Добавьте таблицу снова из списка таблиц
  5. Очистить и построить решение

8
Сначала в EF Code нет .edmx.
Туукка Хаапаниеми

Я дал +1, хотя, потому что он (или кто-то еще с этой проблемой) может захотеть переосмыслить выполнение Code First и сделать это таким образом, вместо этого :)
vapcguy

9

Проблема может быть в строке подключения. Убедитесь, что ваша строка соединения для поставщика SqlClient, без метаданных, связанных с EntityFramework.


Вероятно, это было очевидно для многих, но это оказалось моей проблемой (в отношении смешивания db-first с code-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

Сообщение было довольно ясным, но сначала я его не понял ...

Я работаю с двумя контекстами БД 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

Visual Studio 2019, кажется, вызывает это для меня. Я исправил это, сгенерировав модель edmx снова в 2017 году.


0

Я получаю ту же проблему в Entity Framewrok, и я решил ее с помощью следующих шагов:

1-Откройте ваш Model.edmx 2-измените место в таблице (для изменения в CS-файле) 3-сохраните его

Я надеюсь помочь тебе



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

Это был асинхронный метод, но я забыл поставить await перед GetEntryAsync, и поэтому я получил эту же ошибку ...

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.