Model compatibility exception in Entity Framework - entity-framework

When I execute my web app and try to save data into databse, this exception happens :
Model compatibility cannot be checked because the database does not
contain model metadata. Model compatibility can only be checked for
databases created using Code First or Code First Migrations.
I try lot of issue for resolve this problem , but it persist yet !!

Using migrations isn't really necessary if you're developing on your local machine. You can just set the database Initializer to drop the database always, run some code that interacts with the database, and then you'll see that the database will be recreated and the error will be gone.
Should work, that's how I do it.

delete the database manually, then restart the project with:
public class DbDataContext : DbContext
{
public IDbSet<FlightType> FlightTypes { get; set; }
public DbDataContext()
{
//Validates if database Exists or if is CompatibleWithModel
//Using when Databes is productive - use code first migrations for db changes in this case
//Database.SetInitializer(new ValidateDatabase<DbDataContext>());
//Custom Initializer - crates databse with required entries
//Using while developing
Database.SetInitializer<DbDataContext>(new DatabaseInitializer<DbDataContext>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
DatabaseInitializer:
public class DatabaseInitializer<T> : DropCreateDatabaseIfModelChanges<DbDataContext>
{
protected override void Seed(DbDataContext dbDataContext)
{
dbDataContext.FlightTypes.Add(new FlightType { FlightTypeNummer = "axd", Name = "AXD_LX", IsDefault = true });
base.Seed(dbDataContext);
}
}
ValidateDatabase:
public class ValidateDatabase<TContext> : IDatabaseInitializer<TContext> where TContext : DbContext
{
public void InitializeDatabase(TContext context)
{
if (!context.Database.Exists())
{
throw new InvalidOperationException("Database does not exist");
}
if (!context.Database.CompatibleWithModel(true))
{
throw new InvalidOperationException("The database is not compatible with the entity model.");
}
}
}

Are you trying to use Code-First Migrations? If so, have you run the following command in the Package Manager Console?
PM> Enable-Migrations

Related

EF 6.2.0 shows error 'The model backing context has changed since the database was created' when I update a column on the DB

I am trying to increase the column lenght, by using EF 6.2.0, VS 2019 and SQL Server Management Studio 18,12,1 by creating a new migration and updating manually the model, so that:
I follow the next steps
1.Alter Model by using the next attributes:
[Required]
[StringLength(300)]
public string MyColumn { get; set; }
2. Create new Migration
public override void Up()
{
AlterColumn("myTable", "myColumn", c => c.String(maxLength: 300));
}
public override void Down()
{
AlterColumn("myTable", "myColumn", c => c.String(maxLength: 255));
}
3.Run the Migration in the Package Manager Console
PM> Update-database -force
4.Checking the DB Changes abd the column maxLenght is updated properly
[1]
5.Debug the application but got the next error:
"The model backing context has changed since the database was created"
Any thoughts, will be appreciated!
I solve it by adding the SetInitializer method over the DataContext constructor:
public ReportsDataContext()
: base(Settings.GetConnectionString())
{
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
//*********Adding this line*********
Database.SetInitializer<ReportsDataContext>(null);
InitContext();
}

Entity Framework Code First Initial Create

I first time trying to create web app (.net core 2.1) from scratch with Entity Framework. For some reason I can't get DB generated.
So I installed EF nuget. And did next things:
Added class that inheres from DbContext:
public class ApplicationDbContext:DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Server> Servers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Server>().HasData(
new Server
{
Name = "My Server",
InUse = false
}
);
}
}
And created Entity:
public class Server
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public bool InUse { get; set; }
}
In startup.cs in ConfigureServices method I added:
var connectionString = Configuration.GetConnectionString("ApplicationConnection");
services.AddDbContext<ApplicationDbContext>
(options => options.UseSqlServer(connectionString));
Connection string coming from appsettings and I debugged it so it does coming through, and it same string that I using in other projects with just different Database name value and it should be ok.
Also I run from console Add-Migration command so I got Migrations folder with InitialCreate migration and some snapshot file.
But when I run app I don't get any error but it never hit break point inside InitialCreate.cs migration and so never create DB.
Any ideas where and what should I call to trigger those?
If you want entity framework automatically creates your database
In Configuration file, add this line in constructor:
AutomaticMigrationsEnabled = true;
Then add the code into DBContext:
Database.SetInitializer(new
DropCreateDatabaseAlways<YourDbContext>());
Then when the application already ran:
Database.SetInitializer(new
DropCreateDatabaseIfModelChanges<YourDbContext>());
You can also have a look MigrateDatabaseToLatestVersion
If you manually track version of database:
Update AutomaticMigrationsEnabled = false;
From console, run command Update-Database to migrate your database
manually
So I been able to create DB by adding next code inside Startup.cs in Configure() method
using (var scope = app.ApplicationServices.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
dbContext.Database.Migrate();
if (!dbContext.Servers.Any())
{
dbContext.Servers.Add(new Server
{
Name = "My Server",
InUse = false
});
dbContext.SaveChanges();
}
}

Connection string for code first mode with mysql

I am working on a project that gets connection strings for Entity Framework from environment variables, like this:
public class SomeTests {
[Fact]
public async void TestSomething() {
string connectionString = Environment.GetEnvironmentVariable("APP_CONN_STR");
var appContextOptionsBuilder = new DbContextOptionsBuilder<AppDataContext>();
appContextOptionsBuilder.UseMySql(connectionString); // hardcoded mysql
AppDataContext context = new AppDataContext(appContextOptionsBuilder.Options);
Assert.Equal(context.Country.Count(), 0);
}
}
....
public partial class AppDataContext : DbContext, IAppDataContext
{
public AppDataContext(DbContextOptions options) : base(options)
{
}
public virtual DbSet<Country> Country { get; set; }
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Country>(entity =>
{
entity.ToTable("country");
...
});
...
}
}
The code above is a bootstrapper code for some automated integration testing. Historically every developer is using the same old database instance on the network without a problem. I am trying to make these tests run in an isolated environment, so I have set up an empty new mysql database (using docker to make it reproducible), and let Entity Framework to populate it with a schema.
The problem is, when I create an empty database in this mysql instance and give a connection string to that database, then I am getting table not found errors:
connection str: Server=127.0.0.1;Port=3306;Database=app_mysql_db;Uid=root;Pwd=****;
error: MySql.Data.MySqlClient.MySqlException : Table 'app_mysql_db.country' doesn't exist
I found out that EF will not create tables in existing databases, it will only populate a database with tables if EF itself created it. This is the default behavior of EF.
So I tried to remove the database name from the connection string:
connection str: Server=127.0.0.1;Port=3306;Uid=root;Pwd=****;
error: MySql.Data.MySqlClient.MySqlException : No database selected
So how do I let Entity Framework in Code First mode to create my tables?

Database changes are not vsiisble after executing migrate.exe

I am using entity framework 6.1. I used code-based migration i.e. Migrate.exe to update my database (Add a new property to table). Migrate.exe executed fine and I did refresh on my SQL Server database but the newly added column was not visible.
I inserted a row into the table and checked table and found that now newly column is added to the table.
I would like to know why this newly created column not visible immediately after executing migrate.exe and why I have to hit database to see my update model changes?
Please respond.
I have used below database context and initializer.
public class AMLDBContext : DbContext
{
public DbSet<Template> Templates { get; set; }
public DbSet<Property> Properties { get; set; }
public AMLDBContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<AMLDBContext, Migrations.Configuration>());
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Property>().HasKey(s => new { s.PropertyName, s.TemplateId });
modelBuilder.Entity<ReturnAttribute>().HasKey(s => new { s.AttributeName, s.TemplateId });
base.OnModelCreating(modelBuilder);
}
}
I used below command for migrate.exe.
migrate.exe AutoDbUpgrade.exe /StartUpDirectory:"C:\TestProject\AutoDbUpgrade\AutoDbUpgrade\bin\Debug" /startupConfigurationFile=”AutoDbUpgrade.exe.config” /verbose

Duplicate queries while removing multiple rows in one transaction in Entity Framework 6

I'm working with EF 6 and have the repository class such this:
public class EfRepository<T> : IRepository<T> where T : class
{
private readonly DbContext _context;
public EfRepository(DbContext context)
{
_context = context;
}
....
public void Delete(IEnumerable<T> entities)
{
// skip checks
using (var transaction = _context.Database.BeginTransaction())
{
try
{
_context.Set<T>().RemoveRange(entities);
_context.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
}
}
}
In my controller I have repository instance IRepository<Connection> _repository than binded with Autofac to EfRepository class.
Then I remove multiple items (and everything works fine!):
IEnumerable<Connection> connections = // get some connections;
_repository.Delete(connections); // everything fine - records was removed
But when I open my site with installed MiniProfiler it shows me duplicate sql-query warning:
My question is why I use transactions but still has duplicate sql warning?
Thank you.
This is because Entity Framework currently sends one query per item to be deleted. It does not batch them all into one query. So MiniProfiler is correctly reporting on what is happening - duplicate delete queries (with exception of the param value) are being submitted.
What is your transaction.Commit() doing? Maybe you can add the code of this method to your question.
I am also deleting entites from my database but more like this:
public virtual void Delete(TEntity entityToDelete)
{
if (Context.Entry(entityToDelete).State == EntityState.Detached)
{
DBSet.Attach(entityToDelete);
}
DBSet.Remove(entityToDelete);
}
I think there are no differences between Remove and RemoveRange, but maybe you should check the state first?