EntitySet System.InvalidOperationException - "тип сущности не является частью модели для текущего контекста"

Подобные вопросы

Тип сущности не является частью модели для текущего контекста - и- EF 4.1 Код Первая ошибка - Тип сущности SomeType не является частью модели для текущего контекста. Подобные вопросы, но они представляют собой перспективу "сначала код" только с гораздо более простыми моделями данных, а также с адресной строкой соединения и проблемами отображения. Пожалуйста, внимательно посмотрите на это.

симптом

// HomeController.cs
public ActionResult Index()
{
    var _db = new MealsContext();

    var m = _db.Meals.ToList();
    var d = _db.Drinks.ToList();

    return View();
}

Исключение выдается при получении Drinks коллекция:

The entity type Drink is not part of the model for the current context.

Код

// Meal.cs
public class Meal
{
    public int Id { get; set; }
    public string Stuff { get; set; }
    public virtual ICollection<Meat> Meats { get; set; }
    public virtual ICollection<Vegetable> Vegetables { get; set; }
}

// Meat.cs
public class Meat
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int MealId { get; set; }
}

// Vegetable.cs
public class Vegetable 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int MealId { get; set; }
}

// Drink.cs
public class Drink
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Да, я знаю, что в реальном мире отношения между мясом и овощами с едой, скорее всего, будут "многие ко многим", но не стоит зацикливаться на этом здесь.

// MealsContext.cs
public class MealsContext: DbContext
{               
    public MealsContext() : base("ConnectionString")

    public DbSet<Meal> Meals{ get; set; }
    public DbSet<Meat> Meats{ get; set; }
    public DbSet<Vegetable> Vegetables { get; set; }
    public DbSet<Drink> Drinks{ get; set; }
}

Мой опыт был в использовании методологии Model First. Файл EDMX был построен затем POCO.

В строке подключения находится раздел метаданных, который отображается на проанализированные ресурсы EDMX (metadata=res://*/Models.MealsModels.csdl|res://*/Models.MealsModels.ssdl|res://*/Models.MealsModels.msl;).

Я изучил базовый XML-файл EDMX, в котором показаны все объекты, присутствующие в моделях Conceptual и Store, и все они полностью сопоставлены. WTF?

Поиск проблемы

Первой попыткой было полностью избавиться от хранилища и отображения данных EDMX (SSDL а также MSL секции). Огонь, и теперь есть два исключения:

  1. Получение Meals бросает MSL, error 2062 No mapping specified for instance of the EntitySet and AssociationSet in the EntityContainer,

  2. Получение Drinks продолжает бросать The entity type Drinkis not part of the model for the current context,

Ошибка, брошенная Meals Ожидается, я обстрелял сопоставления и модель магазина - изучаю _db показывает мне, что Meals -> InternalSet -> EntitySet свойство правильное, только не сопоставленное.

Ошибка, брошенная Drinks вот где я застрял. Изучение _db ближе показывает мне, что Drinks -> InternalSet -> EntitySet бросает SystemInvalidOperation Исключение, в котором говорится, что объект не находится в контексте модели.

Вот как CSDL EDMX выглядит в формате XML:

<edmx:ConceptualModels>
  <Schema ...>
    <EntityContainer Name="MealsContext" annotation:LazyLoadingEnabled="true">
      <EntitySet Name="Meals" EntityType="Models.Meal" />
      <EntitySet Name="Meats" EntityType="Models.Meat" />
      <EntitySet Name="Vegetables" EntityType="Models.Vegetable" />
      <EntitySet Name="Drinks" EntityType="Models.Drink" />
      <!-- AssociationSets here for the FKs -->
    </EntityContainer>
    <!-- All are present, but here's the culprit Drink -->
    <EntityType Name="Drink">
      <Key>
        <PropertyRef Name="Id" />
      </Key>
      <Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
      <Property Type="String" Name="Name" Nullable="false" MaxLength="200" FixedLength="false" Unicode="true" />
    </EntityType>
    <!-- Associations here -->
  </Schema>
</edmx:ConceptualModels>

Вопрос

Если DbContext имеет все DbSet свойства и использует строку подключения, которая включает метаданные для модели, которая CSDL правильно определяет тип объекта Drinkпочему, черт возьми, это не является частью контекста?

Единственное, что отличается от Drink Я вижу, что он не связан с другими объектами и не имеет ассоциаций...

2 ответа

Решение

Решаемые.

Первая половина была моим недосмотром. Вторая половина... ну, я не знаю, что было не так. На самом деле это не ошибка или несовместимость, а что-то очень неудобное, прерывистое и сложное для понимания. Сначала краткое изложение, а затем краткое пояснение для тех, кому все равно:

Несмотря на предложения с сообщениями об ошибках, это была не проблема концептуальной модели (CSDL), а проблема сопоставления столбцов, которая периодически создавалась заново.

Концептуальная модель была построена с использованием EdmxWriter разобрать DbContext и его основные части.

Затем модель использовалась для генерации сценариев SQL для передачи схемы в новую базу данных. Хитрость в том, что база данных Oracle.

Oracle является ребенком и не принимает длинные имена столбцов. Таким образом, сгенерированные сценарии EDMX и SQL необходимо было модифицировать, чтобы построить и отобразить части концептуальной модели на усеченные имена столбцов.

Не очень большое дело. Работает нормально. Так где же все пошло не так?

Oracle не поддерживает "сначала код". И хотя это было сделано вручную, используя EdmxWriter представляет собой первый подход кода в глазах Oracle. Поэтому, когда была проанализирована первая схема EDMX, она рассердилась по поводу логических отображений. Решением было временно удалить bools из моих моделей C#, вручную добавить их в EDMX и настроить отображение web.config, которое предлагает Oracle (mapping bool в NUMBER(1,0)).

Все снова отличное. Но почему это повторяется?

В разное время на протяжении всего процесса разработки некоторые стороны соглашения - C#, EDMX или Oracle - меняются. И каждый раз, кажется, столбцы автоматически перераспределяются, и я ничего не знал. Если модель EDMX была обновлена ​​из Oracle, сопоставления указывали на несуществующие свойства C# (короткие имена столбцов). Если модель была обновлена ​​из кода C#, сопоставления не были сохранены, и они пытались сопоставить длинные имена столбцов, которых не было в Oracle.

Облом с этим подходом (сначала гибридный код и сначала модель): если я хочу продолжать управлять своими собственными моделями и работать с настройками, необходимыми для отношения малыша к Oracle, я должен быть очень осторожным и следить за адским файлом EDMX.,

Вам необходимо указать сопоставления для ваших сущностей:

public class MealsContext: DbContext
{               
    public MealsContext() : base("ConnectionString")

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // mappings 
    }    

    public DbSet<Meal> Meals{ get; set; }
    public DbSet<Meat> Meats{ get; set; }
    public DbSet<Vegetable> Vegetables { get; set; }
    public DbSet<Drink> Drinks{ get; set; }
}

У меня была такая же проблема, пока я не начал использовать Entity Framework Power Tools

Используя его, вы можете создавать чистые объекты, такие как бизнес-объекты и классы отображения. Хорошая статья, которая помогла мне создать удивительный слой доступа к данным: Reverse Engineer Code First

Другие вопросы по тегам