I need to make a "full-text indexed" but I am using ef core 2.1 code first migration, but Full Indexes do not have first class support in core.
How can I write my own migration that would be applied while the other generated migrations are being applied?
You have to create empty migration and then in Up method you can write your SQL query.
Create Empty Migration by running Add-Migration command in Package
Manager Console.
Add the SQL function in Up method like the following way.
public partial class your_migration_name : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(#"<YourQuery>");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(#"Drop <YourQuery>");
}
}
Run Update-Database in Package Manager Console.
Related
According to the latest documentation, EF Core supports an --environment parameter, which can be used to define the environment during migration script generation.
I am using it as follows:
dotnet ef migrations script --context:DataContext
-o:migrs.sql 20221024100851_latest_executed_migration -- --environment Production
CLI reports that the parameter is understood:
Build started...
Build succeeded.
info: xxxxx.xxxx[0]
Configuring: 'xxxxx'
Environment: 'Production'
ContentRoot: 'D:\GIT\xxxxx\src\app'
but the script generation still uses the Development environment instead. The following two environment variables are accessible in the C# code:
ASPNETCORE_ENVIRONMENT=Development
DOTNET_ENVIRONMENT=Development
I access the variables using the following command:
public partial class test1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
StringBuilder sb = new StringBuilder();
foreach (DictionaryEntry test in System.Environment.GetEnvironmentVariables())
{
sb.AppendLine(test.Key.ToString() + "=" + test.Value.ToString());
}
migrationBuilder.Sql(sb.ToString());
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
EF Core version 6.0.10 is used.
There is no launchSettings.json file located in the project.
Other SO questions suggest setting the ASPNETCORE_ENVIRONMENT variable in a PowerShell script before command execution, but this is not my goal. I would like to get the new EF Core 5 way working.
Many thanks
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 am trying to use EF Core 3.0 migrations with a hybrid of an existing tables and new tables built with code first. To prevent the scaffolding of the existing tables I would like to decorate the model class with an attribute (fluently or annotations) so that the migration code generation for those tables is skipped but the model is still built into the DbContext class.
The approach I'm taking is to add the following lines to OnConfiguring
optionsBuilder.ReplaceService<IMigrationsSqlGenerator, SkipMigrator>();
And then creating a SkipMigrator with the following code
public class SkipMigrator:SqlServerMigrationsSqlGenerator
{
public SkipMigrator(
MigrationsSqlGeneratorDependencies dependencies,
IMigrationsAnnotationProvider migrationsAnnotations)
: base(dependencies, migrationsAnnotations){}
protected override void Generate(
MigrationOperation operation,
IModel model,
MigrationCommandListBuilder builder)
{
if (operation.FindAnnotation("SkipMigrations")!=null)
{
Console.WriteLine("Skipping table:");
}
else
{
base.Generate(operation,model,builder);
}
}
}
I assumed that the Generate method was what triggered the creation of the migration code file but it never gets called. Id there a different place I should be intercepting the code generation?
If there a different/simpler way to tell migrations to skip tables yet still keep them in my DbContext?
Your means of trying to create your own IMigrationsSqlGenerator was correct, and I've used that approach before to alter the SQL that is generated as part of a migration.
services.AddDbContext<MyDbContext>(opt =>
{
opt.UseSqlServer();
opt.ReplaceService<IMigrationsSqlGenerator, SkipMigrator>();
});
However, as of EF Core 5.0 it's now much easier to exclude specific tables from migrations using the ExcludeFromMigrations() method on a TableBuilder:
public class ReportingContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().ToTable(nameof(Users), t => t.ExcludeFromMigrations());
}
}
More info: https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-efcore-5-0-rc1/#exclude-tables-from-migrations
If there a different/simpler way to tell migrations to skip tables yet still keep them in my DbContext?
Yes, but it requires a different approach.
Instead of using your current DbContext class for creating migrations, create a SecondDbContext class only for the very purpose of creating migrations. This new SecondDbContext class will hold the DbSets<T> that you want EF to do its migrations on.
Then simply specify the second context when calling add-migration UpdateTable -c SecondDbContext and then update-database -c SecondDbContext.
It's a simple task I think.
My requirement is to run one .sql file after all migrations runs successfully.
it contains few alter statements. the system is in a way that I must have to run this Sql, there are no other way like I just update my entity.
I am using asp.net zero architecture.
Right now I am updating my migrations manually and adding this query's with
migrationBuilder.Sql("");
but it's hard to maintain.
I have done some R&D on this topic but not found anything proper.
as I am following best practice of .net boilerplate structure, I would like to hear from boilerplate dev side too.
You can implement the requirement by creating Stored Procedures or Scalar value function.
Create Empty Migration by running Add-Migration command in
Package Manager Console.
Add the SQL query in Up method like the following way.
public partial class testQuery : Migration {
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(#"You query");
}
}
Or
Add Stored Procedures folder and testSP.sql inside it. testSP.sql will have whole SP definition.
protected override void Up(MigrationBuilder migrationBuilder)
{
var spPath = #"MyCompany.MyTemplate.EntityFrameworkCore\Migrations\Stored Procedures\testSP.sql";
var spMigratorPath = Path.Combine("..", spPath);
if (!File.Exists(spMigratorPath))
{
spMigratorPath = Path.Combine("..", "..", "..", "..", spPath);
}
migrationBuilder.Sql(File.ReadAllText(spMigratorPath));
}
Run Update-Database in Package Manager Console.
It will create the function or SP in DB.
Now You can call SP by using ExecuteSqlCommand or ExecuteSqlCommandAsync methods.
You can also refer this.
In Entity Framework by using Enable-Migrations a Migrations folder is created containing a Configuration inherited from DbMigrationsConfiguration like this:
internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
...
}
All the created migrations which are created using Add-Migration are placed in the Migrations folder too.
public partial class Init: DbMigration
{
public override void Up()
{
...
}
public override void Down()
{
...
}
}
I didn't find any code that relates these two together ( for example having a configuration property in migrations). The only relation I found is that both are placed in same folder. If I have more than 1 DbContext and consequently more than 1 Configuration, I'm wondering how these DbMigrations are distinguished?
Question: How DbMigration classes are related to a Configuration?
They are related by convention. By default, it will store the migrations in a root folder called Migrations. You can override this in the constructor of the config (https://msdn.microsoft.com/en-us/library/system.data.entity.migrations.dbmigrationsconfiguration(v=vs.113).aspx) or when you enable-migrations:
public Configuration()
{
AutomaticMigrationsEnabled = true;
MigrationsDirectory = #"Migrations\Context1";
}
For multiple contexts, create a different config and folder for each by using -ContextTypeName ProjectName.Models.Context2 -MigrationsDirectory:Migrations\Context2. Here is a walkthrough: http://www.dotnettricks.com/learn/entityframework/entity-framework-6-code-first-migrations-with-multiple-data-contexts
When you run the update-database command, the database operations in the up() method in the latest DbMigration derived classes is performed. If that is successful, the commands in the Configuration class are executed. One of those methods is the seed() method where you can optionally add code to plug values into your tables after a migration. When you specify a target migration (presumably earlier than the latest), the migration works through the chain of down() methods in the migration classes to get to the version you wanted.