EntitySet System.InvalidOperationException - "тип сущности не является частью модели для текущего контекста"
Подобные вопросы
Тип сущности
симптом
// 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
секции). Огонь, и теперь есть два исключения:
Получение
Meals
бросаетMSL, error 2062 No mapping specified for instance of the EntitySet and AssociationSet in the EntityContainer
,Получение
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