Exception thrown when using pre-generated views - entity-framework

In my project I have the following setup.
EF6 installed
Code first migration running
Views pre-generated using Entity Framework Power Tools
MVC project
This has been working fine up until now where after adding a new code first migration, and then regenerating the views, I can see the following error:
The current model no longer matches the model used to pre-generate the mapping views, as indicated by the fooClass.MappingHashValue property.
Pre-generated mapping views must be either regenerated using the current model or removed if mapping views generated at runtime should be used instead. See http://go.microsoft.com/fwlink/?LinkId=318050 for more information on Entity Framework mapping views.
There was no error generated at all when creating the migration, which is properly formed, and the database does manage to migrate perfectly well. The exception arises when running the MVC site.
For completeness sake, the model change is as following:
public class MyClass
{
[Key]
public int MyClassId
//various other properties
public int Version //newly added property
}
and the migration generated is:
public partial class AddingVersionNumber : DbMigration
{
public override void Up()
{
AddColumn("dbo.MyClass", "Version", c => c.Int(nullable: false));
}
public override void Down()
{
DropColumn("dbo.MyClass", "Version");
}
}
Reverting back to the previous migration, removing the migration changes and then regenerating the views works perfectly fine as well.
I have also tried just adding in a random model change to see if it was anything wrong with the specific table I was changing, but this test change failed with the same error. Seems that no matter how I change the model, the same error re-appears.
Another test I followed was to deleted the pre-generated views file from the project, but still the same exception is thrown.
Anyone else ever experienced anything similar?

Related

Manually modifying EF Code First Migration step without perturbations

I know we cannot manually update code inside DbMigration method because this can lead us to an inconsistent state for the next DbMigration step.
So, for example, if I change nullable: false to nullable: true in the code of the DBMigration step below (and at the same time do the same modification in the entity class) this will certainly gives problems. The right way is to apply modification only inside the entity class and to add an new DBMigration step in the Package Manager Console (Add-Migration).
public partial class AddDisabledOnUser : DbMigration
{
public override void Up()
{
AddColumn("dbo.Users", "Disabledc => c.Boolean(nullable: false));
}
public override void Down()
{
DropColumn("dbo.Users", "Disabled");
}
}
But what about DBMigration step with SQL commands like below:
public partial class UpdateSomeUsers : DbMigration
{
public override void Up()
{
Sql("UPDATE Users SET Remark = 'Blah blah' WHERE UserName like 'ABC'");
}
public override void Down()
{
}
}
Can I modify the sql code inside the SQL command without affecting the DBMigration steps?
Can I add more sql commands inside an existing DBMigration step without affecting the DBMigration steps?
Do you confirm I can only do thing that did not modify entity models ?
Thanks.
Changing a migration which has already been applied to the DB won't have any effect, therefore I assume you want to change a migration before running it against the DB. If this is the case, then your problem is not really a problem:
If you want to change a property or another aspect of the model, do it, then add the same migration again with the -Force switch, or delete the migration and add it again. Now the migration will match your model just fine
If you want to add extra SQL statements, just do it as you mention adding one or more Sql("...") to the migration file. It doesn't make a difference how many times you change them.
The only problem with manually modifying the migration file is that if you have to recreate the migration, you have to be careful not to forget to add the manual changes again. To avoid that, what I do is to customize the migrations SQL generation so that I can specify my custom SQL code in the mapping files.

Should we add Entity Framework dll to all layers

I am writing a test app using EF code first. I have distributed code among different layers. I thought I would have to install the entity framework package to the data access layer only but what I ended up with is installing the package (adding dlls) to all the layers namely UI, BLL, Models, DAL. Is this okay or I am doing something wrong. Below is sample code to give you an idea of what I am trying to do
Model Layer
This layer is reference in all other layers/projects
namespace Model
{
Public class Sample
{
[ForeignKey("Sample2Id")]
...
}
}
In this layer I had to use Entity Framework dlls because of Data Annotation like [ForeignKey..
DAL
namespace DAL
{
public class SampleContext:DbContext
{
...
}
}
In DAL I only have the context class and migrations
BLL
namespace BLL
{
public class SampleBLL
{
public List<Sample> GetAll()
{
retrn new SampleContext().Samples().ToList()
}
}
}
If I uninstall EF for BLL I get the following error
The type System.Data.Entity.DbContext is defined in an assembly that is not referenced.
UI
namespace UI
{
public class UIHelper
{
public List<Sample> GetSamples()
{
return new SampleBLL().GetAll();
}
}
}
If I uninstall the EF package from UI I get the following error
The Entity Framework provider type
'System.Data.Entity.SqlServer.SqlProviderServices,
EntityFramework.SqlServer' registered in the application config file
for the ADO.NET provider with invariant name 'System.Data.SqlClient'
could not be loaded. Make sure that the assembly-qualified name is
used and that the assembly is available to the running application
I created a sample project which is quite similar to your current setup minus the Model Layer/DAL separation.
I have three projects, DAL (which contains references to the EntityFramework.dll and the EntityFramework.SqlServer.dll), BLL which just calls a method in the DAL, and the UI which just calls the BLL methods.
I had to add the <configSections>, the <entityFramework>, and the <connectionStrings> portions of the app.config of the DAL into the UI's app.config.
When I ran the code the first time, I ran into the same error you ran into. So I looked into the debug folder of my UI Project and noticed that the EntityFramework.dll was copied into the folder due to the DAL's dependency on it. I also noticed that the EntityFramework.SqlServer.dll was NOT copied into the debug folder despite the DAL also having a dependency on it.
I copied the EntityFramework.SqlServer.dll into the debug folder of the UI Project then re-ran the project then, Viola! My code ran as expected.
It looks like the problem here is that one dll is not being copied into the UI Project debug folder as it is expected to.

Is DBContext added automatically with EF 6 or must it be added manuall?

New to EF. Following along with DBContext by Lerman/Miller.
When I start a new project, adding EF6 (Database First), the DBContext seems to be added as a default (ie I don't have to add the DBContext separately with T4). Also, for Lazy Loading, the "virtual" needed in the class definitions also seems to be there by default (I don't have to add it like in the book). Is this what is expected?
When you use Database First approach and use EF x DbContext Generator it creates the DbContext for you automatically and set the navigation properties, virtual. If you want to disable lazy loading you can simply use following code
public class MyContext : DbContext
{
public MyContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
Most probably the books you are reading are for code first development. If you use database first(especially with the designer) you don't need to make changes.

EF: Getting "The model backing ...has changed" error, though I've altered well the schema

I am not worried about rollbacks (ie: Down() method), and would like to work always on the latest code modification, so I'm not using Code Migrations.
I changed this:
int SomeProperty {get; set;}
To this:
int? SomeProperty {get; set;}
And then I modified the database schema (altering the column SomeProperty to allow NULLS).
Although this last part, I'm still getting the error:
The model backing the <Database> context has changed ...
What other change do I need to do so that the schema matches the model if that (int to int?) is the only change I've done?
Tell EF you want to do an automatic migration
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, MyMigrationConfiguration>());
Context.Database.Initialize(true);
public abstract class MyMigrationConfiguration<TContext> : DbMigrationsConfiguration<TContext>
where TContext : DbContext{
protected MyMigrationConfiguration() {
AutomaticMigrationsEnabled = true; //<<<<<<<<<<<<<<<<<<<
AutomaticMigrationDataLossAllowed = true;
}
EDIT: Added comment based on feedback
Changing the Database to Match the schema means also the Migration history table will also need to be altered if it doesnt match. Setting the Model Data binary by hand to match your model, is not straight forward.
If your tables match your code, then the model recorded in __MigrationHistory as the last model, must be different. Your problem starts right there.
You can delete all entries from MigrationHistory table and try again. [disclaimer.. take a copy of entries... etc] But fighting EF isnt the ideal approach.
It also means you are in quasi DB first mode. So i would suggest you DON'T continue on this path. Unless you plan on going to DB First mode.
What you are saying is you dont trust EF to do the right thing under code first scenarios.
Backup the DB. Then try it. If EF does the "WRONG" thing try and deal with that would be my suggestion. If you have a nasty migration scenario EF cant handle, start a new question to get workarounds.
The real answer to this is a bug in EF.
In Global.asax.cs this line is needed:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//...
// Weird fix before using any DbContext instance <--- THIS
Database.SetInitializer<MyDbContext>(null);
}

EF 4.1 Code First error - The entity type SomeType is not part of the model for the current context

While working with EF code first I get error given below at different times:
The entity type SomeType is not part of the model for the current context.
What are the possible causes of this error?
It may occur because:
DbContext configured with an incorrect connection string
The entity specified is actually not mapped in configuration
I got this when my class that inherited from DbContext did not declare the model as a property. For example, I neglected to add a property for FooModel in the code below:
public class MyDBContext : DbContext
{
public DbSet<FooModel> FooModels{ get; set; }
// etc. ...
}
This message also appears if you try to do somthing such a set an EntityState on a child collection in a one-to-many association.
For example; if a one-to-many association exists between ParentEnt and ChildEnt in the code snippet below, the error message:
The entity type Hash1Type is not part of the model for the current context.
MyDbContext.Entry(ParentEnt.ChildEnt).State = EntityState.Unchanged;
The following change does not produce an error:
MyDbContext.Entry(ParentEnd.ChildEnt.First).State = EntityState.Unchanged;
Note that the use of First() in this case may indicate t
This can also be caused by properties on your POCO not named EXACTLY as they are in the EDMX/modelbuilder. Please see my post here for details on how I trouble shot the issue.
The entity type <class> is not part of the model for the current context
I had this error.
It turned out I had added a new field to a db View a few hours before. I updated the context (as part of something else I was doing) and got this error.
When I updated the POCO's all was well: EF threw this error because it could not map a field in the View to a property in the POCO of the View.
Not the most helpful error message in this situation IMO.
It may happen when your model is not mapped correctly to your Class. In my case I got this error when I used EF Model First and when I updated my EDMX model from DB but didn't update my Entity class. Specifically a property in Entity was in lower case while in DB and EDMX diagram was in Upper case.
And another issue I had was a model property in EDMX diagram was not converted to my app Enum So that EF couldn't recognize that Entity.
I've been doing database first and using the built in template generation for my models (EF 4.1)
I copied the generated code into a new file and removed the navigation properties. That's when I started to see this error. I have lazy loading turned off, but it appears the navigation properties are still necessary in the POCO's.
I suppose the error might indicate that your model is missing something.
namespace TestApp.BLL
{
using System;
using System.Collections.Generic;
public partial class User
{
public User()
{
//this.Roles = new HashSet<Role>();
}
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
//public virtual ICollection<Role> Roles { get; set; }
}
}
The above code shows the navigation properties commented out. If I uncomment them on all POCO's (that means the Role POCO too) the exception goes away.
UPDATE
This error kept attacking me with various updates I made to the database. Eventually I deleted the edmx file and just created it again with the same tables and stored procs.
Old
I got this when the generated entity was missing a nullable column:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MyProgram.Models
{
using System;
using System.Collections.Generic;
public partial class Question
{
public int id { get; set; }
public string title { get; set; }
public string body { get; set; }
public string tags { get; set; }
public int votes { get; set; }//I had to manually add this property which is nullable int in the database
}
}
I added the property after generating the initial model. However, I even tried deleting the table and recreating it. That didn't fix it. Only adding the property manually fixed it for me.
Answering the question is "What are the possible causes of this error?":
This error seems to occur any time the internal/EDMX model is not successfully built, or is not completely built. And there are a large potential number of causes for this problem. It's unfortunate that there seems to be insufficient error reporting or error detection when building the model, so solving it seems to involve trying a bunch of things to see what makes the problem go away.
I ran into another instance of this error over the past few days, using EF 6.0 (currently pre-release code), code-first, and custom conventions. It turns out that the root cause is that I had a custom convention which renames the ID EdmProperty (eg ID -> MyTypeId). If I disabled my custom convention this problem went away; if I enabled my convention the problem occurs. There is no logging or exceptions or other errors to indicate that a problem occurred when the building the model. This exception doesn't rear its head until I try to add an entity to a DbSet. The convention didn't cause any problem when generating the database (via Migrations).
In my scenario I was using EF6 to migrate a MySQL database to MSSQL. I had 2 separate models and contexts, each with their own connection string. The classes had the same name, but the MySQL one was all lowercase and the MSSQL one Pascal casing. I had copied in both connection strings from the relevant assemblies containing my EDMX models. But when I ran my application I got an error about one of the 2 connection strings having been already added to the dictionary list.
So I removed the conflicted entry, foolishly thinking it somehow had access to the connection string in the assembly's own app.config (it's late!). But no, the error was actually happening because both connection strings also had the same name - one all lowercase and one in Pascal casing - i.e. the Dictionary key ignores the casing. So when I removed the MySQL one, it then attempted to use the MSSQL connection string for BOTH models. So I had to re-add, rename and manually set the connection string for the second model in code.