I am trying to create a migration for a MYSQL database with EF 6 and running into problem where MYSQL exception is thrown informing that the table is not found. From what i see the problem comes from the fact that migrations have a dbo. prefix on the statements. Manually changing the migration file and removing the dbo. part works.
The strange thing here is that the error only occurs when there is a second migration exists and after examining the first migration file i noticed that its also have a dbo. prefix but still database creation happens correctly and the exception is only thrown once database is being migrated to second version.
When database created there is no dbo. prefixes on the tables or any other database part even when dbo. prefixes exists in initial create migration so it makes me wonder that there must be some part of the code that takes care of it?
Migration code:
public partial class Update1 : DbMigration
{
public override void Up()
{
AddColumn("dbo.ProductOrderLine", "SomeData_Id", c => c.Int());
CreateIndex("dbo.ProductOrderLine", "SomeData_Id");
AddForeignKey("dbo.ProductOrderLine", "SomeData_Id", "dbo.User", "UserId");
}
public override void Down()
{
DropForeignKey("dbo.ProductOrderLine", "SomeData_Id", "dbo.User");
DropIndex("dbo.ProductOrderLine", new[] { "SomeData_Id" });
DropColumn("dbo.ProductOrderLine", "SomeData_Id");
}
}
Exception when downgrading, Funny enough upgrading worked.
Reverting migrations: [201508280829293_Update1].
Reverting explicit migration: 201508280829293_Update1.
alter table `dbo.ProductOrderLine` drop foreign key `FK_dbo.ProductOrderLine_dbo.User_SomeData_Id`
MySql.Data.MySqlClient.MySqlException (0x80004005): Table '_gizmo_db.dbo.productorderline' doesn't exist
Here i am able to run database update but after that downgrade fails.
Ok it seems that the problem was that i didn't had MySqlMigrationCodeGenerator set as migration code generator and that was causing the generation of dbo prefixes which lead to drop/create problems.
Related
I've recently added a migration to my data model where I added a bool property to the Member model:
public class Member
{
public bool IsLegacy { get; set; }
}
Having added the migration via dotnet ef migrations add <name>, the migration generated code to create every table.
As a result, when I push the migration to the database dotnet ef database update, I get an error saying
table '...' already exists
The existing table could change from time to time.
I would expect the migration to simply add the column to the table so that the only could would probably be something like:
public partial class AddedLegacyFieldToMember : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsLegacy",
table: "Member",
type: "bit" // assuming sql type is what it needs.
);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn("IsLegacy", "Members");
}
}
So what I can't figure out is why the migration is trying to build every table all new as though no other migration exists.
The migration history table in the database does have the previous migration listed there though.
Have I done something wrong?
Note
I've tried using .EnsureCreated() to sidestep the issue, but clearly that's misguided as it didn't make any difference.
Also, building the migration logic into the Startup doesn't address the problem either.
I have a class that includes 2 properties: Value and Description. These 2 properties were added to the class a couple of Migrations back and there was never a problem.
Today, while working on a branch I noticed that when I added a new Migration it was scaffolded to once again add the columns, so I started doing some testing.
Starting from the current baseline, with no entity changes, if I add a Migration called "Test", I get this:
using Microsoft.EntityFrameworkCore.Migrations;
namespace AgWare.Data.Migrations
{
public partial class Test : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
Which is correct, I haven't made any changes to my Models. Git only shows the new Migration and its Designer.cs files as added, with no changes to the Snapshot. Now, if I run Remove Migration, the Test Migration is removed but suddenly Git says that my Snapshot has changed, with the following lines having been deleted from the modelBulder entry for the above-mentioned class:
b.Property<decimal?>("Value")
.HasColumnType("Money");
b.Property<string>("Description")
.HasMaxLength(75);
So removing a Migration which had nothing to do with these properties somehow results in updating the Snapshot to reflect that they have been removed for some reason. This means when I add another Migration it will generate code to create these columns again, which won't work since they already exist. What could be the cause of this? I want to figure this out now so this doesn't become a reoccurrence for all future Migrations.
I'm writing a web api attached to a database that I created using Model First.
Being new I was confusing Model First with Code First.
As it's my first EF/Web app I didn't realize that migration wasn't yet implemented by Model First and I followed the procedure to implement it. When it ran I received some errors, looked them up and only then realized I'd need to remove it again.
Following somebody's instructions I deleted the migrations folder, plus the _migrationHistory table from the database.
But now I receive the following exception whenever the _migrationhistory table is missing from the database.
protected void Application_Start()
{
// Call initializer
Database.SetInitializer(new PulseDbInitializer());
new ApplicationDbContext().Database.Initialize(true); <- error here
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
"An exception of type 'System.NotSupportedException' occurred in EntityFramework.dll but was not handled in user code
Additional information: 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."
The following is a partial description of my initializer
public partial class PulseDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>, IPulseDbInit
//public partial class PulseDbInitializer :DropCreateDatabaseAlways<ApplicationDbContext>, IPulseDbInit
{
private ApplicationDbContext _context;
protected override void Seed(ApplicationDbContext context)
{
_context = context;
var pid = new PulseDbInitializionData(context);
pid.Init(this);
}
}// class PulseDbInitializer
It seems that the app is trying to use migrations (because it's creating the _migrationhistory table) even though I've removed the migrations subfolder.
Being new at this, I'm not sure where to go. I'm aware that I've created my initializer, see above, so am I missing something?
EDIT - Too long for a comment
Im not sure we're understanding each other.
Very simply, I don't know what's generating the _MigrationHistory table in my database as afaik if I remove the Migration subdirectory from my project and delete the database, then I thought that's all I need to do to drop migrations.
In my model first, the DropCreateDatabaseIfModelChanges is what I've always used for generating the database and is working as expected. It creates a new database, or recreates when the model changes.
Until I added the migration I didn't notice this _MigrationHistory table and I don't have a clue if the add-migration command added any code to my project that I need to delete or change (I really hate things happening and not being told exactly what was done in some kind of log. Please microsoft, for future reference)
Or am I totally wrong and the _MigrationHistory table was always there but I never noticed? It all seems to work, as long as I don't remove the table.
Your initializer is inheriting from DropCreateDatabaseIfModelChanges, which checks for model changes. Since you are not using code first you can't check for model changes in code (since your code doesn't define the model -that'd be code-first-... the model defines the code -that's model-first-)... so you need to implement your own IDatabaseInitializer which only checks (for example) that the database exists:
public partial class PulseDbInitializer : IDatabaseInitializer<ApplicationDbContext>, IPulseDbInit
{
public void InitializeDatabase(ApplicationDbContext context)
{
var exists = new DatabaseTableChecker().AnyModelTableExists(context.InternalContext);
if (exists == DatabaseExistenceState.Exists)
{
// maybe check if certain data exists and call the `Seed` method if
// it doesn't
return;
}
// Throw some error if it doesn't exist
}
protected override void Seed(ApplicationDbContext context)
{
_context = context;
var pid = new PulseDbInitializionData(context);
pid.Init(this);
}
}
I am new to Code first, can you tell me how i can have all Up and Down methods for all tables in the database like below(given for one table)
public partial class abc: DbMigration
{
public override void Up()
{
AddColumn("dbo.UserTasks", "ServiceTechReason", c => c.Long());
}
public override void Down()
{
DropColumn("dbo.UserTasks", "ServiceTechReason");
}
}
i want all three types for a table viz .cs , .Designer.cs , .resx.
2) Can you explain the above example, i pick it from somewhere on internet i was searching for this but found nothing. is abc is my table name in database?
Provide me link if it is already answered.
EDIT
As mentioned by #scheien i already tried those commands they do not automatically override up and down methods for a table
Creating migrations is done by running the command Add-Migration AddedServiceTechReason.
This assumes that you have already enabled migrations using the Enable-Migrations command.
To apply the current migration to the database, you'd run the Update-Database. This command will apply all pending migrations.
The point of Code-First migrations is that you make the changes you want to your Entity(ies), and then add a new migration using the Add-Migration command. It will then create a class that inherits DbMigration, with the Up() and Down() methods filled with the changes you have made to your entity/entities.
As per #SteveGreenes comment: It does pick up all changes to your entities, so you don't need to run it once per table/entity.
If you want to customize the generated migration files, look under the section "Customizing Migrations" in the article listed.
All these commands are run in the package manager console.
View -> Other windows -> Package Manager Console.
Here's a great article from blogs.msdn.com that explains it in detail.
I've added two new properties to my domain model class and two properties to a data table accordingly. Then I tried to launch my mvc web application and got
The model backing the 'EFDbContext' context has changed since the database was created.
Consider using Code First Migrations to update the database
(http://go.microsoft.com/fwlink/?LinkId=238269).
Having read the following posts:
MVC3 and Code First Migrations
EF 4.3 Automatic Migrations Walkthrough
I tried to Update-Database through Package Manager Console, but got an error
Get-Package : Не удается найти параметр, соответствующий имени параметра "ProjectName".
C:\Work\MVC\packages\EntityFramework.5.0.0\tools\EntityFramework.psm1:611 знак:40
+ $package = Get-Package -ProjectName <<<< $project.FullName | ?{ $_.Id -eq 'EntityFramework' }
+ CategoryInfo : InvalidArgument: (:) [Get-Package], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,NuGet.PowerShell.Commands.GetPackageCommand
The EntityFramework package is not installed on project 'Domain'.
But the Entityframework is installed on project Domain. I removed it from references, deleted package.config and sucessfully reinstalled EF. But Update-Database still returns same error. Update-Database -Config does as well
What am I doing wrong?
EDIT
Many thanks to Ladislav Mrnka, I'll try to rephrase my question. As far as I changed my data table manually, I am not expected to use migration. But how can I now make EF work with manually edited domain model class and data table?
Try to add this to startup of your application (you can put it to App_Start):
Database.SetInitializer<EFDbContext>(null);
It should turn off all logic related to handling the database from EF. You will now be fully responsible for keeping your database in sync with your model.
I had the same problem and this is how I fixed the issue.
I dropped table __MigrationHistory using sql command and run the update-database -verbose again.
Apparently something was wrong with this automatic created table.
Answer 2 was exactly what was needed. Although when I got to the App_Start I realized that there were 4 configuration files and didn't see where this would fit in any of them. Instead I added it to my EF database context
namespace JobTrack.Concrete
{
public class EFDbContext : DbContext
{
//Set the entity framework database context to the connection name
//in the Webconfig file for our SQL Server data source QSJTDB1
public EFDbContext() : base("name=EFDbConnection")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Remove the tight dependency on the entity framework that
//wants to take control of the database. EF by nature wants
//to drive the database so that the database changes conform
//to the model changes in the application. This will remove the
//control from the EF and leave the changes to the database admin
//side so that it continues to be in sync with the model.
Database.SetInitializer<EFDbContext>(null);
//Remove the default pluaralization of model names
//This will allow us to work with database table names that are singular
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
//Allows for multiple entries of the class State to be used with
//interface objects such as IQueryTables for the State database table
public DbSet<State> State { get; set; }
}
}