EntitySet System.InvalidOperationException - "the entity type is not part of the model for the current context"

one.beat.consumer picture one.beat.consumer · Nov 29, 2012 · Viewed 33.9k times · Source

Similar Questions

The entity type <classname> is not part of the model for the current context -and- EF 4.1 Code First error - The entity type SomeType is not part of the model for the current context are similar questions but they are "code first" perspective only, with much simpler data models, and address connection string and mapping issues. Please look closely at this one.

Symptom

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

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

    return View();
}

Exception is thrown retrieving the Drinks collection:

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

Code

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

Yes, I know in the real world the relationship between Meat and Vegetable with Meals would likely be Many-to-Many but don't get hung up on it here.

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

My experience was in using a Model First methodology. The EDMX file was built then the POCOs.

In the connection string is the metadata section that maps to the parsed EDMX resources (metadata=res://*/Models.MealsModels.csdl|res://*/Models.MealsModels.ssdl|res://*/Models.MealsModels.msl;).

I examined the underlying XML of the EDMX file shows all entities present in Conceptual and Store models, and all are fully mapped. WTF?

Troubleshooting

The first tried was to completely get rid of the store and mapping EDMX data (the SSDL and MSL sections). Fire away, and now there are two exceptions:

  1. Retrieving Meals throws MSL, error 2062 No mapping specified for instance of the EntitySet and AssociationSet in the EntityContainer.

  2. Retrieving Drinks continues to throw The entity type Drinkis not part of the model for the current context.

The error thrown by Meals is expected, I nuked the mappings and store model -- examining _db shows me that Meals -> InternalSet -> EntitySet property is correct, just not mapped.

The error thrown by Drinks is where I am stuck. Examining _db closer shows me that Drinks -> InternalSet -> EntitySet throws the SystemInvalidOperation exception that states the entity is not in the model context.

Here's what the EDMX's CSDL looks like in XML format:

<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>

Question

If the DbContext has all the DbSet properties and is consuming a connection string that includes metadata for a model who's CSDL correctly defines the entity type Drink, why in the hell is it not part of the context?

The only thing different about Drink that I can see is that it is not related to any other entities, and has no associations...

Answer

one.beat.consumer picture one.beat.consumer · Dec 3, 2012

Solved.

The first half was my oversight. The second half... well I don't have a word for what was wrong. It is not really a bug, or incompatibility, but something very inconvenient, intermittent and hard to figure out. First a summary, and then the length explanation for those who care:

Despite the error message suggestions, it was not a problem with the conceptual model (CSDL), but a column mapping issue that recreated itself intermittently.

The conceptual model was built using the EdmxWriter to parse the DbContext and its underlying pieces.

The model then was used to generate SQL scripts to push the schema to a new database. The trick is, the database is Oracle.

Oracle is a baby and does not accept long column names. So the generated EDMX and SQL Scripts had to be modified to build and map parts of the conceptual model to truncated column names.

Not really a big deal. It works fine. So where did things go wrong?

Oracle does not support "code first". And even though it was done manually, using the EdmxWriter constitutes a code-first approach in Oracle's eyes. So when the first EDMX schema was parsed, it bitched about boolean mappings. The solution was to temporarily remove the bools from my C# models, add them to the EDMX manually and make the web.config mapping Oracle suggests (mapping bool to NUMBER(1,0)).

Everything is groovy again. But why does it keep reoccurring?

At different times throughout the development process some ends of the agreement - either C#, EDMX, or Oracle - are altered. And each time, it seems the columns were automatically remapped and I was unaware. If the EDMX model was refreshed from Oracle, the mappings were pointing to C# properties that didn't exist (the short column names). If the model was refreshed from C# code the mappings were not preserved and they attempted to map to long column names that weren't in Oracle.

The bummer with this approach (sort of hybrid code first and model first) is if I want to continue managing my own models and handle customizations necessary for Oracle's little baby attitude, I have to be very careful and monitor the hell out of the EDMX file.