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?
Related
I am trying to correct the casing of some tables in my model by using Data Annotations in Entity Framework 6.
Some tables in the database are wrongly cased as SomeTable but cannot be renamed.
The fix for this should be in the model like this:
[Table("SomeTable")]
public class Sometable
{
…
}
However, this wrongly triggers a migration in the Entity Framework which includes both a CreateTable("SomeTable") and a DropTable("SomeTable") in the same Up() method, which obviously does not make sense.
Is there any way to force Entity Framework to understand that this table actually exists and it is just the casing that have changed?
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.
I created POCO classes and then EF created the database tables for me when I tried to access the data. This worked without problem. I have now populated my tables with data. Not just seed data but real data.
Now I would like to add another column to a table. I assume the first thing I need to do is to add a field to the POCO class but what's next after that? I now have my database filled with data. On the SQL side I know how to add the column myself but do I have to do something with EF or will it automatically pick up that my column was added to the table and my field to the POCO class?
You can use Code First Migrations (http://msdn.microsoft.com/en-us/library/hh770484(v=vs.103).aspx). It can update your database automatically or not.
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 am trying to create a custom Entity Framework (4.2) entity that would be mapped to my database like it would be done in a Code first approach.
The issue is that my entity framework data model is using Database first.
How can I add my custom entity to entity framework's context?
If by the Database first you mean that you already have EDMX created from exiting database you simply cannot use code first. You must create table and update model (EDMX) from the database to include it in EDMX.
Edit based on comment:
I want to create a BriefUser entity that would basically be a lighter
version of User but it would have properties retrieved from User's
foreign keys.
Well this is possible. You can either create BriefUser as common class and use projection in query.
var breifUser = (from x in context.Users
where ...
select new BriefUser
{
// Fill BreifUser's properties here
}).FirstOrDefault();
You can even refactor former code to reusable extension method:
public static IQueryable<BriefUser> ProjectUser(this IQueryable<User> query)
{
return query.Select(x => new BreifUser()
{ // Fill BreifUser's properties here });
}
and use it like:
var briefUser = context.Users.ProjectUser().FirstOrDefault(...);
It is also possible to define your new class as "entity view". The first problem is that each table can be mapped to only one entity (except some advanced concepts like inheritance or splitting) so you cannot define your BriefUser as a new entity type because mapping both User and BriefUser to UserTbl would violate this rule. You must use special construct called QueryView.
QueryView is view in mapping level. It allows you to create new mapped type which is projection of existing mapped entities defined directly in EDMX's MSL part. The projection is defined as custom Entity SQL query. The problem is that QueryView has limitations:
It doesn't offer all Entity SQL features - for example it doesn't support aggregations (which I consider as really missing feature). Without aggregations you for example cannot create a new type which will contain property counting some related entities.
It is not supported in designer. You must edit your EDMX as XML to define QueryView and you must write Entity SQL query yourselves.
Resulting type is a "view" and it is read-only.
I want to keep the EDMX file, but also be able to add an entity
(BriefUser) to EF's context.
This is not possible. Your BreifUser is only projection / view and EF is not able to track changes back to originating tables so you cannot add BreifUser to context and persist it. In case of QueryView you can achieve it if you define custom stored procedures which will no how to decompose BreifUser and modify all related tables. These stored procedures must be imported to the EDMX and mapped to data modification operations of the view entity. Btw. same will happen if you map your entity to the database view because EF takes all views as read-only.