I have a project that just started using EF Migrations.
There is an initial migration and an additional, hand-edited migration that defines indexed views. There is no other migration.
I recently added a single property to one class. When I create a new schema, the property is created. However, I cannot see why it is created, since the property is not mentioned in any migration.
If I search the entire source code folder (with subfolders, .) for any mention of that property name, it does not appear in any EF migration code (it only appears in the class where it is defined, and in a few lines of code where the property is accessed).
When I set a breakpoint at the beginning and end of the Up() method for the two existing migrations, I can see that the table is created without the additional property by the initial migration (verified in SSMS), and that the property does not yet exist at the end of the last Up() migration. Sometime after control leaves the last migration, some code creates a column in the database for this additional property.
To try and track this down, I hand-edited this new property into the initial migration. Now, after the Up() method for the last migration exits, I get an SqlException
Column names in each table must be unique. Column name 'MyNewProperty' in table 'dbo.MyTable' is specified more than once.
in the constructor for my DbContext.
The stack trace only shows the code that is instantiating DbContext.
How can I track down where this additional migration is coming from?
If you are not explicitly adding a code-based migration for this new property (using add-migration), but a column is being created it can be determined that automatic migrations are enabled.
Automatic migrations allow Entity Framework to automatically determine the schema changes required to represent any changes made to the domain model, this is what is adding your new column.
You are also wondering why it still tries to add the new column even after you hand edit a code-based migration to add this new column; for each code-based migration there is a generated code-behind file (.Designer.cs) which contains a string IMigrationMetadata.Target property, this returns a string snapshot of what the domain model will look like after this migration has been applied.
When you edit the migration file by hand, this Target property still returns the old string representation of the domain, which does not contain your new property; as a result of this, automatic migrations then attempts to add a duplicate column.
The solution to this is to add your new property to the domain then use the add-migration command to add a new code-based migration for this new property.
Related
I am working on a new application in .Net 5 using EF Core. After creating some entity classes and doing the first few migrations I discovered that I wanted to change the data type of column and make it the key in one of the tables. I was able to do that without issue and the app works just fine with that change - but now if I try to change anything else in that table like add a new column and do a migration I get the following error: "To change the IDENTITY property of a column, the column needs to be dropped and recreated." I have tried even dropping the entire table - but nothing seems to work.
Whenever your migrations get messed up, especially early in a project, just delete the migrations folder, drop the Migration History table and start fresh with a new initial migration.
I'm trying to move property Tenant (of Type Tenant) from subclass to base class. I'm using TPH strategy and since I already have column Tenant_Id I would expect no changes in the migration.
However Entity Framework generates such a migration:
DropForeignKey("dbo.JobDetailsBases", "Tenant_Id", "dbo.Tenants");
AddColumn("dbo.JobDetailsBases", "Tenant_Id1", c => c.Guid());
CreateIndex("dbo.JobDetailsBases", "Tenant_Id1");
AddForeignKey("dbo.JobDetailsBases", "Tenant_Id1", "dbo.Tenants", "Id");
How can I tell EF to utilize the same column? I don't want to have column Tenant_Id1 for obvious reasons..
Update: I was trying to do it in two steps.. First remove the property from the subclass, generate the migration and then add in the base class and generate another migrations. I was hoping that this will improve the situation - it didn't.
The problem is that the first migrations is generated empty - EF does not want to remove that field. I updated the migration to remove it, but it still stays somehow in the model. The result is that even if I add this back EF will generate it like that (still with Tenant_Id1):
AddColumn("dbo.JobDetailsBases", "Tenant_Id1", c => c.Guid());
CreateIndex("dbo.JobDetailsBases", "Tenant_Id1");
AddForeignKey("dbo.JobDetailsBases", "Tenant_Id1", "dbo.Tenants", "Id");
So now the question is: how can I alter the internal EF model to get rid of the original property which I already removed from the class?
My application uses Entity Framework 5.0 code-first on top of a Sql CE database. Until now, we have used Automatic Migrations to manage entity mapping changes. However, I now have a change for which I need to create a custom migration to ensure no data is lost during the update. I made my changes to the entities, and used the Add-Migration command which generated Up() and Down() methods for me. I customized the Up() method to insert my custom sql to preserve the data, and tested my application.
When I run the application, I received the error:
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
Ok, I don't understand this because all of my changes are detailed in the Up() method that got executed.
So I turn Automatic Migrations back on just to see what happens. Now I receive this error:
"Cannot alter column of type NTEXT or IMAGE [ Column Name = LastName ]"
This error comes from a table/entity that hasn't even been touched with my changes. The existing database has this string mapped to nvarchar(4000). If I examine the DB after I receive this exception, I observe that the columns have been changed to ntext. What is EF doing? Why is it touching tables that haven't been changed? How can I get more information on what is going on here?
Update:
As a workaround, I attempted to mark each and every string type in my entities with a data annotation as such:
[Column(TypeName = "ntext")]
public virtual string LastName
{
get;
set;
}
Now all of my strings are using ntext in the database. This leads to further exceptions when queries are performed:
The ntext and image data types cannot be used in WHERE, HAVING, GROUP BY, ON, or IN clauses, except when these data types are used with the LIKE or IS NULL predicates.
So, to summarize:
Turning off automatic migrations causes EF to detect phantom changes and throw exceptions
Turning on automatic migration in conjunction with a custom migration causes all existing strings to be mapped to ntext
strings mapped to ntext cannot be queried, effectively making them useless in my application
For me, a modification of an Up method worked out.
SerialNumber = c.String(maxLength: 99)
was applied instead of
SerialNumber = c.String()
i had the same issue and i fixed by editing the table column data type manually by opening SQl Server Compact/SQlite Toolbox explorer windows, and then expend the database name, then expend the table you want to edit and right click the column you want to edit, and click drop script, then run the scrip and the column will be dropped from the table, then right click the table and click add column and from here you can choose what data type you want and add the new column that way. I hope this helps some one.
Now i'm using EF6 Alpha, and when using migration, it will add a new migration log into the __MigrationHistory table.
In EF6, The __MigrationHistory table has a new column called "ContextKey". After testing, I found there are two default "ContextKey" value:
The full name of DbContext's derived class.This happens when i run the code:
Database.CreateIfNotExists();
The full name of DbMigrationsConfiguration's derived class. This happens when i run the code:
public ArticleDbContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ArticleDbContext, ArticleConfiguration>());
}
The first time i run the application, "Database.CreateIfNotExists();" create a new database for me, also all tables that map to the models defined in ArticleDbContext, and then add a __MigrationHistory row which ContextKey's value is "Module.Article.Model.ArticleDbContext".
And then "Database.SetInitializer(new MigrateDatabaseToLatestVersion());" will be runned, this code will generate a new ContextKey "PowerEasy.Module.Article.Migrations.ArticleConfiguration". Migration query the __MigrationHistory table with this ContextKey and find out there's no data. So again it will create all tables that map to the models defined in ArticleDbContext, but the tables are already exist in the database, so an exception will be throwed, and tell me "the table XXX is already existed".
How can i solve this?
You should not mix Migrations and the Database.CreateIfNotExists method (or any of the initializers built on top of it). Migrations will take care of creating the database if it does not already exist.
As an alternative to the Migrations initializer, you can also apply migrations using the DbMigrator.Update method. This is useful if you want to create/update the database before it would otherwise be triggered by the initializer.
I have a project that I recently migrated from VS2010 to VS2012.
It contains an EF4.1 edmx file containing my entities. A few of these entities are based on views and are read-only. Although some columns returned by the views are nullable, I have changed the return value of these columns in the view to ensure that they do not return null by using
ISNULL(NumericColumnName, 0) AS NumericValueColumn
When updating the model via the "Update Model From Database" function in VS2010, the columns that were returned in this way were being created as non-nullable in my model. However, since the move to VS2012, this is no longer the case.
Now, whenever I use the "Update Model From Database" functionality, these properties are generated as nullable. What I have to do is manually set the columns to non-nullable. However, the entity properties will be regenerated as nullable the next time that I run "Update Model From Database". I then have to update them to non-nullable again.
Another work-around that I have tried is to move the view-based entities to their own edmx file. However, I am seeing the same behavior when updating either of the edmx files.
Another detail is that I am using Self-Tracking Entities, generated via the EF4.1 T4 STE templates.
Is there any way to prevent the VS2012's EF designer from overwriting my non-nullable attribute for the view-based entities?
EDIT
It turns out that the designer in VS2012 is trying to prevent you from shooting yourself in the foot, and consequently changes the member properties inside my entity.
When generating a member from the following:
SELECT ISNULL(Quantity,0) * ISNULL(Number, 0) AS Total FROM SomeTable
VS2012 will always set the member Total on the SomeTable entity to nullable because it does not understand that there is no way for the result of the multiplication to be 0. To prevent this behavior, change it to:
SELECT ISNULL(Quantity * Number, 0) AS Total FROM SomeTable.
Watch out for aggregations as ISNULL(SUM(SomeCol),0) is not the same as SUM(ISNULL(SomeCol,0)).