I've created a new class, and EF will create a migration code when I'll do add-migration in Package Manager Console. Since this table is a classifier, I want to populate it with data and include this data in migration. I cannot use Seed method, since i'll be using my generated migration on production database later on.
Where should I hardcode the values for this table? I can edit the generated migration cs file, but this seems an inelegant solution. Could you recommend more proper place to define the data?
I think if you're goal is to populate your table for development/testing, there's no reason you shouldn't do you data seeding via the Seed method. You could always wrap the seed code for this table with an if block that checks your connection string values.
Edit:
If you plan to populate your table in your production database with the same data, it would certainly make sense to do so in the Up method of that specific migration that creates the table.
Related
Hi I created my database using Entity Framework core with code first approach. Now there is a change in the column type from int to varchar/string? I can change the column from the database itself but my understanding is that it won't be a good idea and would create issues. I searched through but I didn't get my answer on the net for Entity framework core.
You should use EF Core migrations to update your db schema. The documentation is pretty good, so make sure to go through it.
However, this is a summary of how the process would be:
Make the change in your model (which by convention will be automatically detected. Alternatively, use the Fluent API in your DB Context OnCreate method or in your EntityConfigurations).
Add a migration running the following CLI command : dotnet ef migrations add SomeDescriptiveNameAboutWhatThisMigrationWillDo.
A migration file with an Up and Down method will be automatically generated. The Up will be run when you apply the migration, and the Down if you ever decide to revert it . You could add changes to the automatically scaffolded migration file. Based on the code in the migration file, EF Core will then generate a SQL script and apply the changes to the DB.
Once you have added (and maybe edited) the migration file, you need to apply it to the DB. You do that by running dotnet ef migrations update.
EF Core tracks all applied migrations in a table in your DB called by default __EFMigrationsHistory
In your particular case of changing a column type, EF Core might try to drop the column and recreate it, which will result in data loss. If you wanna keep your data, I would recommend altering the migration script to actually split the process in two: first add a new column with the new type and a slightly different name, then write some custom SQL to migrate data from the old column to the new one, then delete the old column and finally rename the new column to the correct name. To be honest, I am not sure if there is some custom migration operation that will out of the box change the data type without data loss, there might be.
To double check if the migration will generate data loss or check if it will do what you expect it to do, you can generate the SQL script that will be used by running dotnet ef migrations script <from migration> <to migration>. After reviewing it, you can either copy/paste and run the script in your DB, or just run the command detailed in step 4 above.
You can modify your database schema to match your domain model with the add-migration command.
After changing the type of the property on your c# class from int to string, simply run
add-migration <SomeDescriptiveName>
After the creation of the migration files, you can apply them with the update-database command.
You can read more about migrations here.
I need to add a new column / property to my database and my model without EF Code First dropping my database.
Is there a way to manually map a column to property so EF would not drop my database?
Update:
Got it to work by following this post on SO.
https://stackoverflow.com/questions/6049135/manually-editing-database-in-code-first-entity-framework
Basically you just need to:
Manually add the column to your database
Manually add the property to your model
Disable any database initializer in your DataContext
As long you're using anything beyond EF 4.3, you would use Migrations to do so. You can't do it manually because EF relies on the model that is stored in order to best do the mapping to SQL. When you make a change it refreshes the model. Any attempt to add something without changing the model will result in an exception.
I'm building my EF (v4.0.30319) data model from my SQL Server database. Each table has Created and Updated fields populated via database triggers.
This database is the backend of a ASP.NET Web API application and I recently discovered a problem. The problem is, since the Created and Updated fields are not populated in the model passed into the api endpoint, they are written to the database as NULL. This overwrites any values already in the database for those properties.
I discovered I can edit the EF data model and just delete those two columns from the entity. It works and the datetimes are not overwritten with NULL. But this leads to another, less serious but more annoying, problem... my data model has a bunch of tables that contain these properties and all the tables need to be updated by removing these two columns.
Is there a way to tell EF to ignore certain columns in entities across the entire data model without manually deleting them?
As far as I know, no. Generating the model from the database is going to always create all of the fields from the database table. Well, as long as it has a primary key it will.
It is possible to only update the fields that you want i.e. don't include the "Created" and "Updated" fields in your create and update methods. I'd have to say though, that I'd think it'd be better if those fields didn't even exist on the model at that point. You may at one point see those fields on the model and not remember that they won't get persisted to the DB.
You may want to look into just inserting the datetimes into those fields when you call your create() and update() methods. Then you could just ditch the triggers. You'd obviously want to use a class library for all of your database operations so this functionality would be in one place. To keep it nice and neat, you know?
I need to configure the database created by Entity Framework Code First MigrateDatabaseToLatestVersion class.
Is it possible to influence the database files parameters like size or maxsize? What interests me in particular, is there a way to add database files?
I assume I need to find the moment where the Entity Framework generates the CREATE DATABASE statement and influence it a bit. As far as I understand, the SqlServerMigrationSqlGenerator class is too late because the database already exists at this point.
Edit: According to comment this doesn't work:
You can just add code based migration using Add-Migration command and modify its Up method to execute Sql("ALTER DATABASE ...") and do what ever you want with your database.
Database is created through DbProviderServices - that is a bridging component between EF and specific database server. ObjectContext exposes operations for creating database and generating database creation script. DbMigrator use database creation operation when you execute Update. It checks that if Database exists and if not it uses ObjectContext.CreateDatabase. So if you want to change the process of creating the database you need to implement your own implementation of the migrator to change the way how Update method generates the database (maybe you just need a decorator which will create a database prior to executing DbMigrator.Update operation).
I want to programmatically create the database create script for my EF 4.3 Code-First database. The database creates just fine using the standard DatabaseInitializer mechanisms, but the following code fails:
using(var dc = new MyContext())
{
var objContext = (IObjectContextAdapter)dc;
var script = objContext.ObjectContext.CreateDatabaseScript();
}
The exception I get is:
The store generated pattern 'Computed' is not supported for properties that are not of type 'timestamp' or 'rowversion'.
I do have a Computed column defined of type "string" but like i said, the database creates fine when created via the built-in DatabaseInitializer. Oddly enough, the resulting schema using this method doesn't actually create a computed column.
As to why I'm doing this, I have a script that runs post-create that drops this column and creates a bonafide computed column. Without specifying the column as computed in the EF mapping, it will attempt to assign that column a value upon inserts, which then fails.
Leaving database creation aside for a moment, setting “Computed” means that EF will not attempt to write the value of that column but will read the value that was (presumably) computer by the server each time the column is queried. From an EF perspective it is valid to have a computed column for any data type.
Now consider database creation from the EF model. EF doesn’t know what to do to create the computed column in the database, and indeed it may not even be possible to do it without triggers in certain databases depending on the type of the column. So in EF4 the decision was made to make CreateDatabaseScript throw in these situations.
However, EF 4.3 and later don’t use CreateDatabaseScript anymore when targeting SQL Server or SQL Server Compact. They instead use the Migrations pipeline. For the Migrations pipeline we decided to take a different approach because we felt that it was wrong for database creation to always throw for what could be a perfectly valid model. Especially considering you could have written your own SQL in the migration that added a trigger or some other mechanism to make the database create a valid computed column.
So this is why you see the database being created by EF 4.3 (but without doing anything to make the column computed) but then you see the same model throw when trying to use CreateDatabaseScript which uses the older, non-Migrations mechanisms.
The way to fix this is to have Migrations create the scripts instead of using CreateDatabaseScript.